Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: OOP - Is this possible?

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.