Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Colonel Taint
Mar 14, 2004


Brecht posted:

Did you profile the code using std::strings vs. your "optimized" C strings, and document the statistically significant difference? It's kind of a rhetorical question because I'm sure you didn't. Would you be willing to paste your complete code somewhere? If so, I'm willing to rewrite it with std::strings and prove it to be as-fast or faster as your version, if-and-only-if you'd be willing to repent from your sinful lifestyle of fragile, error-prone preoptimization. Will you agree to that? Praise Meyers, Hallelujah!

It's on. http://github.com/rainey/texthash

vvv ah it's not so bad. Admittedly not the best or neatest I've written, but I didn't really plan on sharing this with anyone.

Colonel Taint fucked around with this message at 21:59 on May 17, 2010

Adbot
ADBOT LOVES YOU

Brecht
Nov 7, 2009

SintaxError posted:

It's on. http://github.com/rainey/texthash
Ugh, Christ, what have I gotten myself into.

Fair warning, I don't run Windows, so I'm chucking your timer code out completely in favor of the Unix 'time' command, which means I'm counting time spent loading the words to memory.

*soldiers onward*

edit: Your code doesn't print out a sum, and when I modified it to do so, the number it printed was incorrect. So maybe fix that first :) I'm guessing it's because of your case insensitive hash but I may be wrong. http://pastebin.com/tvv15DWK for the reference implementation I used to come to this conclusion.

Brecht fucked around with this message at 22:01 on May 17, 2010

Colonel Taint
Mar 14, 2004


Alright I looked into it... something is definitely hosed here. I looked into the summing issue, and it seems entryList for some reason wants to play a game of Tetraheism Tetraheism chwartzlot.

code:
        int i = 0;
	entryList[0] = strtok(buffer[0], delim);
	
	cout << entryList[0] << endl;	//Tetraheism
	
	while(entryList[i] != NULL && i < numEntries)
	{
		entryVals[i] = atoi(strtok(NULL, delim));
		entryList[++i] = strtok(NULL, delim);
	}
	
	cout << entryList[0] << endl;	//Tetraheism
	
	lookupList[0] = strtok(buffer[1], delim);
	cout << entryList[0] << endl;	//Tetraheism
	i = 0;
	while(lookupList[i] != NULL && i < numLookups)
	{
		lookupList[++i] = strtok(NULL, delim);
	}
	
	cout << entryList[0] << endl;	//chwartzlot
No idea why it changes after/during that loop. If it didn't, the sum would be curiously off by 1.

Colonel Taint fucked around with this message at 23:25 on May 17, 2010

Brecht
Nov 7, 2009

SintaxError posted:

Alright I looked into it... something is definitely hosed here.
I don't know if it's causing your problem, but never use strtok.

Colonel Taint
Mar 14, 2004


Alright, I still have no idea why that pointer was getting modified, but the working code is up at http://github.com/rainey/texthash if you still want to run the timer on it. I just had to reset entryList[0] to the start of the buffer after running that loop.

Edit: I doubt anyone really cares anymore, but the error was caused by the lookupList index going out of bounds at the end of the loop.

Also, the most recent version at github has Windows based timers replaced with functionality from sys/time.h

Colonel Taint fucked around with this message at 03:34 on May 18, 2010

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


If a class has a private default constructor (and ONLY that constructor), if said class is instantiated by a friend factory function, can that instance be copied/assigned from? Or do I have to explicitly put operator= and copy constructor under private too?

(edit) I'd try it for myself on codepad but my work is resolving maybe a tenth of the sites I try to go to and codepad is in the other nine tenths along with google :(

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ledneh posted:

If a class has a private default constructor (and ONLY that constructor), if said class is instantiated by a friend factory function, can that instance be copied/assigned from? Or do I have to explicitly put operator= and copy constructor under private too?

Yes. Implicitly-declared destructors, constructors, and copy assignment operators are always public.

EDIT: And I think you mean assigned *to*. Of course some other class can provide a public assignment operator / constructor / whatever that takes a reference to your class, and there's no way to prevent this with access control.

rjmccall fucked around with this message at 19:38 on May 18, 2010

Ciaphas
Nov 20, 2005

> BEWARE, COWARD :ovr:


rjmccall posted:

Yes. Implicitly-declared destructors, constructors, and copy assignment operators are always public.

EDIT: And I think you mean assigned *to*. Of course some other class can provide a public assignment operator / constructor / whatever that takes a reference to your class, and there's no way to prevent this with access control.

Yeah, I meant to, not from. Thanks :)

Lowclock
Oct 26, 2005
I'm pretty awful at C++. I finished this assignment for class and it works the way it should, but I wanted to figure something else out for myself. Here's the terrible loop I have.

code:
do
{	
	cout << "Want to draw another tree?" << endl;
	cin.ignore();
	cin.get(again);
	if(again != 'n' && again != 'N' && again != 'y' && again != 'Y')
		{
		cout << "Sorry, that's not a valid answer. Please use Y for Yes, or N for No." << endl;
		}
	}
while(again != 'y' && again != 'Y' && again != 'n' && again != 'N');
Originally I just had cin >> again;, but that causes some issues if you enter more than one character. I figured this would throw the first char captured from the stream into again, so that if someone tries to type out Yes or No instead of just y or n, it would still work, but instead it just behaves the same as when I just used cin, with the added side effect that if anything is put after y it will make the rest of my program get stuck in a loop.

I know this probably looks terrible, but I'm just learning. Here's the rest of it if you want to take a look and tell me anything I can do differently or better.

Vanadium
Jan 8, 2005

I think cin.ignore() only ignores one character, you probably want cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') to ignore up to the next newline character.

raminasi
Jan 25, 2005

a last drink with no ice
Is it possible to build an unmanaged DLL in MSVS 2010 that can be used by unmanaged code compiled in MSVS 2005? It seems like it should be trivial, but I am getting crashes consistent with incompatible runtimes that happen even when the only runtime library switch I know about it set correctly (e.g. /MDd or /MD). Is there some other option I need to set?

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Well if you're linking to different versions of the CRT, you are probably going to have some issues. I think VS2010 lets you use older compilers though (or their settings, or something).

raminasi
Jan 25, 2005

a last drink with no ice
Yeah, I think I just found it.

Microsoft posted:

If you have a .lib or .obj file that needs to link to msvcrt.lib, then you should not have to recompile it to work with the new msvcrt.lib in Visual C++ 2010. The .lib or .obj file may rely on the sizes, field offsets, or member function names of various CRT classes or variables, and those should all still exist in a compatible way. When you relink against msvcrt.lib, your final EXE and DLL image will now have a dependency on msvcr100.dll instead of msvcrt.dll.

If you have more than one DLL or EXE, then you may have more than one CRT, whether or not you are using different versions of Visual C++. For example, statically linking the CRT into multiple DLLs can present the same problem. Developers encountering this problem with static CRTs have been instructed to compile with /MD to use the CRT DLL. Now that the CRT DLL has been renamed to msvcr100.dll, applications may have some components linked to msvcrt.dll and others to msvcr100.dll. If your DLLs pass CRT resources across the msvcrt.dll and msvcr100.dll boundary, you will encounter issues with mismatched CRTs and need to recompile your project with Visual C++ 2010.

If I'm reading that right, the problem is just going from 2010 to before 2010. 2010 lets you use the 2008 runtime (I think), except I don't have 2008 installed. It just seems like a weird incompatibility gap.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Yeah, if your DLL is linking to msvc[10 or whatever].dll, you'll get runtime errors on a system that only has the 2005 version. All you'll probably need to do is put the msvc[10 or whatever].dll & manifest into the dll search path alongside your dll.

dll

raminasi
Jan 25, 2005

a last drink with no ice
But I can't very well tell 2005 not to link against *any* runtime (at least it doesn't seem like I should try to do that), can I? The problem isn't that it can't find the file it needs, the problem is that I can't pass data between the two.

And even if it were possible to do something like that I really want my DLL to "just work," which is not really compatible with that solution.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
From everything you've described, it sounds like the the OS runtime is 1) loading your DLL when the program-written-in-VS2005 loads, 2) trying to load the msvc10.dll because your DLL depends on it, and then 3) crashing because it can't find msvc10.dll. Visual Studio isn't part of those three steps.

If your DLL depends on other DLLs, then you can't pass it around by itself; it's no different than a program in that respect.

raminasi
Jan 25, 2005

a last drink with no ice
I guess I wasn't being clear then. The crash wasn't from it not finding msvcr100[d].dll, it was in some low-level stdio stuff that comes about when you try to operate on a FILE * created by one CRT in a different one. I know this error, I've gotten it before, and it's exactly what the Microsoft documentation says will happen.

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
Well, the only answer is "don't do that".

raminasi
Jan 25, 2005

a last drink with no ice
Yep, and I'm not.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
http://blog.llvm.org/2010/05/clang-builds-boost.html

Optimus Prime Ribs
Jul 25, 2007

Is there is a significant performance difference between this, if any?

code:
for(int i = 0; i < 100; i++)
{
	int value = i;
}
and
code:
int value = 0;
for(int i = 0; i < 100; i++)
{
	value = i;
}

BattleMaster
Aug 14, 2000

Optimus Prime Ribs posted:

Is there is a significant performance difference between this, if any?

code:
for(int i = 0; i < 100; i++)
{
	int value = i;
}
and
code:
int value = 0;
for(int i = 0; i < 100; i++)
{
	value = i;
}

Why would you do either of those things? :psyduck:

Edit: If that's just a really incomplete snippet then the second one would probably be a bit faster because of fewer stack operations

BattleMaster fucked around with this message at 06:41 on May 24, 2010

shrughes
Oct 11, 2008

(call/cc call/cc)
I just realized you could do destructuring assignment in C++.

code:
#include <iostream>


template <class T, class U>
class destruc {
  T& first;
  U& second;

 public:
  destruc(T& tref, U& uref) : first(tref), second(uref) { }

  void operator=(std::pair<T, U> p) {
    first = p.first;
    second = p.second;
  }
};

template <class T, class U>
destruc<T, U> p(T& first, U& second) {
  return destruc<T, U>(first, second);
}

int main() {
  int x; double y;

  p(x, y) = std::make_pair(2, 3.0);

  std::cout << "x is " << x << " and y is " << y << std::endl;
}

Optimus Prime Ribs
Jul 25, 2007

BattleMaster posted:

Why would you do either of those things? :psyduck:

I didn't mean that literally. I just used a 1...100 for loop as an example.
It was easier than posting/explaining the code I'm working with.

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.

BattleMaster posted:

Edit: If that's just a really incomplete snippet then the second one would probably be a bit faster because of fewer stack operations

Yes, but any compiler worth its salt would probably generate exactly the same machine code for both versions. The first (declared inside the for loop) might actually end up being faster if it allows the compiler to do further optimizations because of the locality of the variable. Making variables as local as possible also helps keep code maintainable because you don't need to look so far up to see the declaration and there's less code that the variable could be interacting with.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

shrughes posted:

I just realized you could do destructuring assignment in C++.

This is tr1::tie.

Optimus Prime Rib posted:

I didn't mean that literally

The correct answer to the question you literally asked is that an optimizing compiler will eliminate both of these loops completely because they have no effect (†). Does that help answer the question you didn't literally ask? The performance of code will depend on how it can be optimized; optimizers can make extremely aggressive changes to code; what optimizations apply to a variable depend on how the variable is used; thus it doesn't usually mean much to talk about the performance about tiny pieces of code in isolation.

That said, Mr.Radar is right. The only difference in formal semantics between these loops is that, in the second one, the value of 'value' is preserved between iterations. Since you overwrite 'value' without reading from it at the beginning of each iteration, the optimizer will know that it doesn't need to preserve anything, so there will be absolutely no difference. But with a different loop body, having the variable declared outside the loop could introduce false dependencies between iterations (or intentional dependencies between iterations, of course).

† Some optimizing compilers won't do this for "sufficiently obvious" no-op loops out of an (IMO misguided) attempt to preserve user-written delay loops. It's important to understand that this involves carving a specific exception out of an otherwise general optimization; the compiler isn't being stupid, it's intentionally trusting the programmer not to have been that stupid — and like I said, I think it's generally wrong to.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

This is one of those things that is actually trivial to try out. gcc -s reveals:

code:
        .text
.globl _main
_main:
LFB3:
        pushq   %rbp
LCFI0:
        movq    %rsp, %rbp
LCFI1:
        movl    $0, -4(%rbp)
        jmp     L2
L3:
        movl    -4(%rbp), %eax
        movl    %eax, -8(%rbp)
        incl    -4(%rbp)
L2:
        cmpl    $99, -4(%rbp)
        jle     L3
        leave
        ret
code:
        .text
.globl _main
_main:
LFB3:
        pushq   %rbp
LCFI0:
        movq    %rsp, %rbp
LCFI1:
        movl    $0, -4(%rbp)
        jmp     L2
L3:
        movl    -4(%rbp), %eax
        movl    %eax, -8(%rbp)
        incl    -4(%rbp)
L2:
        cmpl    $99, -4(%rbp)
        jle     L3
        leave
        ret
respectively, so the first doesn't have any extra overhead.

RonniePudding
Oct 18, 2005

Is is possible to initialize a static const array with a for loop?

Below code doesn't work because I'm trying to change a const array after it's been initialized. If I remove the const and static it will work, but I lose the "static const" status.

code:

static const float floatLookup[256]; 
 
void initLookup()
{
    for(int i=0;i<257;i++)
    {
    	floatLookup[i] = i*(1.f/255.f);
    }
}

Avenging Dentist
Oct 1, 2005

oh my god is that a circular saw that does not go in my mouth aaaaagh
No.

RonniePudding
Oct 18, 2005

Ok, figured as much. I'll just cout the values and paste that into my initialization.

Thanks

Optimus Prime Ribs
Jul 25, 2007

Mr.Radar posted:

Yes, but any compiler worth its salt would probably generate exactly the same machine code for both versions........

rjmccall posted:

That said, Mr.Radar is right. The only difference in formal semantics between these loops is that, in the second one, the value of 'value' is preserved between iterations........

All right, thanks.

I didn't think posting my actual code was necessary since it seemed like a simple question to me. v:shobon:v
Won't do that next time.

Anyway, thanks again.

POKEMAN SAM
Jul 8, 2004

RonniePudding posted:

Is is possible to initialize a static const array with a for loop?

Below code doesn't work because I'm trying to change a const array after it's been initialized. If I remove the const and static it will work, but I lose the "static const" status.

code:

static const float floatLookup[256]; 
 
void initLookup()
{
    for(int i=0;i<257;i++)
    {
    	floatLookup[i] = i*(1.f/255.f);
    }
}

Argh there is a real horror in here.

Hint: 257

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

Ugg boots posted:

Argh there is a real horror in here.

Hint: 257

I'm kind of wondering why a lookup table is necessary for f(i) = i / 255.

I almost had a working solution for this that used template metaprogramming, recursion, and variadic templates to build up an array initializer, but I got stuck since C++ doesn't permit floats as template arguments.

That Turkey Story
Mar 30, 2003

RonniePudding posted:

Is is possible to initialize a static const array with a for loop?

Below code doesn't work because I'm trying to change a const array after it's been initialized. If I remove the const and static it will work, but I lose the "static const" status.

code:

static const float floatLookup[256]; 
 
void initLookup()
{
    for(int i=0;i<257;i++)
    {
    	floatLookup[i] = i*(1.f/255.f);
    }
}

Not with a for loop, but you can do this in the current standard with preprocessor metaprogramming.

If you have boost:

code:
#include <boost/preprocessor/repetition/enum.hpp>

#define ARRAY_INIT_MACRO( z, value, data ) value * ( 1.f / 255.f )

const float floatLookup[] = { BOOST_PP_ENUM( 256, ARRAY_INIT_MACRO, ~ ) };

// Don't pollute!
#undef ARRAY_INIT_MACRO

POKEMAN SAM
Jul 8, 2004

Flobbster posted:

I almost had a working solution for this that used template metaprogramming, recursion, and variadic templates to build up an array initializer, but I got stuck since C++ doesn't permit floats as template arguments.

Do more bit manipulation? :D

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

Ugg boots posted:

Do more bit manipulation? :D

I did consider just using reinterpret_cast as a hack everywhere, but I couldn't bring myself to do it. That was just going too far.

RonniePudding
Oct 18, 2005

Turkey, thanks, I'll look into that.

Another question:

Is there a way in C++ to compare two byte arrays without cycling through each byte?

Currently I'm doing:

code:
    for(int i=0;i<BUFFERLENGTH;i++)
    {
    	if(bufferOld[i] != bufferNew[i])
        {
           //doIt();
        }
    }
Is there a better way to do it?

Flobbster posted:

I'm kind of wondering why a lookup table is necessary for f(i) = i / 255.

I'm rendering a webpage to a texture in Unity, so that specific portion calculates one component of a pixel every loop (byte to float), so the quicker the better. This actually bought me 10fps by using a lookup table.



Ugg boots posted:


Argh there is a real horror in here.

Hint: 257


It's sample code! :) ...and I'm a terrible programmer

*edit clarification

RonniePudding fucked around with this message at 00:33 on May 26, 2010

OddObserver
Apr 3, 2009
std::memcmp might help you (doesn't give you the index of difference, which you might need based on your pseudocode, though).

Edit: why are you using a float texture format?

The1ManMoshPit
Apr 17, 2005

RonniePudding posted:

Is there a way in C++ to compare two byte arrays without cycling through each byte?

memcmp from the c standard library or std::equal from the c++ STL algorithm library (your comparison would be std::equal(bufferOld, bufferOld + BUFFERLENGTH, bufferNew)).

Adbot
ADBOT LOVES YOU

RonniePudding
Oct 18, 2005

Holy hell that's awesome, thanks guys. I just found memmove() too which will help.

quote:

why are you using a float texture format?

That's what Unity game engine requires me to use in order to dynamically create a texture and update it.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply