Author: Ratko V Tomic
Date: 06:09:37 03/28/02
Go up one level in this thread
>Hmm, I think I understand what you are saying, but I'm not bundling global >variables into classes. If I have a class member it's because I need to have >multiple instances, in C it would have been a struct anyway. The problem here is that the automatic instance creation in C++ may be orders of magnitude more expensive than a custom code you could tailor to the specific task. For example in generating multiple instances of the class Board, saying board=new Board(); turns into calls to dynamic memory allocator and to the constructor. Doing it manually, you could have worked from prealloced array of boards (or a singly linked list) and the manual 'creation' may be as simple as a single inline statement: board=(board_heap+=board_size);. If necessary you could also do memset(board,0,BDSZ); if you need to clear it, or do memcpy(board,board0,BDSZ) where the compiler will produce inline form of these functions. The same issues come up in the destructor phase. In this example you could save a lot of code by not assuming that board size can arbitrary i.e. instead of using general purpose allocator (as C++ new would use) you can use a simple heap. If you also know that the board[] will be created/destroyed in the last-in-first-out manner, the alloc and dealloc are simple one statement add/subtract from the board_heap variable. The C++ 'new' is insensitive to such custom circumstances -- it will create the code as if you may decide at runtime to have each 'board' in different size and as if they will be destroyed in any order. You can gain great deal of performance by taking advantage of the fixed size allocator and of the LIFO constraint. > I see that you need to fetch the pointer and toss it to the > function, but how is it different from C where you pass the > pointer manually in the argument list? > Are you saying that it can be done in C without a pointer? If the functionality in C++ is optimally partitioned and any un-needed generality of C++ objects is not deployed, than it could be almost the same. But you may not know what is the optimal partition of functionality until you have the whole code in front of you, which is well after the time you have layed out your classes and bult up on top of such initial decision. (In C you need far less of this kind of up-front commitment.) And then by the time you re-optimize, to remove all un-needed C++ generalities and the implicit mechanical busy work it generates, and take advantage of all the special circumstances, such as in the example of board above, you end up with .C code in the .CPP named files. Which, you then realize, you could have done to start with and would have been done in less time for this same level of tight optimization. In C the CPU work at runtime mirrors much closer the coding work than in C++. Since during the coding phase you naturally try to spare yourself from the un-needed busy work (by taking advantage of special circumstances whenever possible), you will consequently spare the CPU from the un-needed work at run-time. Coding in C++ (and in the commonly taught styles) you're removed farther from the 'busy work' through the automated class & object facilities. This is fine if performance doesn't matter much. But the mindless cookie-cutter code it spews out will impair perceptibly the performance in the core parts of the chess engines (or low level graphics engines, compression algorithms, etc). > That wouldn't surprise me a bit, still it won't be necessary > if there is only one instance of the function(?). It matters only whether a member could be subclassed. If it can, (and the compiler won't know whether you will subclass it from some other module when it is compiling the first module) the calls to such members will go through the indirect call. (This is entirely unrelated to C++ overloading.) >>some examples from your code to see how the ECX register gets >>almost always reserved for 'this' pointer, making it out of >>limits for other more beneficial immediate use (in addition to >>the overheads of the above indirections). > >You have failed to convince me that this should be a bad thing, it actually >sound like an optimization to me. The compiler knows that we'll be working on >the object for quite a while ... Well, this is not a religious or political issue to require convincing, but something that a simple inspection of the ASM code generated will answer for you quite clearly. The issue is how are registers used in the innermost code loops. Just because you may need the class pointer on a longer span of code doesn't mean that during the execution that class pointer would be fetched most frequently (if no register were used to hold it). Counting the frequency of substring occurence of a variable name in the source doesn't work well as a measure of the frequency of the dynamic variable access.
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.