Maker Pro
Maker Pro

Writing Scalabe Software in C++

S

Stephen Sprunk

MooseFET said:
That is simply false. Why do you think it can't be done with
virtual methods?

It can, of course.
Virtual methods when done the way that Borland Pascal, Delphi
and a good implementation of C++ add very little extra time to
the total run time. The virtual method dispatch code takes less
instructions than the entry code of most routines.

True. However, in this particular example, we're comparing the cost of
using virtual methods to select 32- and 64-bit code paths vs. the cost of
emulating 64-bit all the time.

* You have to do a vtable lookup
* You have to get the parameters into the right registers or, worse, in the
right places on the stack
* You have to call the function
* You have to do a function prolog
* Do the work
* You have to do a function epilog
* You have to return from the function
* You have to get the results from the return register or stack to where you
want it.

All of those steps need to be done in series, because they depend on each
other. You also lose the ability to schedule multiple such operations in
parallel or one operation in parallel with other code, greatly increasing
latency and reducing performance. Finally, there's significant additional
costs if you have L1-I misses, BHT misses, stack-based arguments, etc.

Compare all of that vs. just emulating a 64-bit type (assuming a 32-bit CPU)
for all math. It's obvious to anyone who understands CPU architecture which
will win. Skybuck's the only one who doesn't get it, for obvious reasons.

S
 
D

David Brown

Skybuck said:
For those that missed the other threads here is the explanation why I want
something like this:

For 32 bit compilers:

int (32 bit signed integer) is fast, it's translated to single 32 bit cpu
instructions.

long long (64 bit signed integer) is slow, it's translated to multiple 32
bit cpu instructions.

For 64 bit compilers

long long (64 bit signed integer) should be fast, it's translated to a
single 64 bit cpu instruction.

I want to write code just once ! not three times ! and I want maximum speed
!

Look, it's quite simple - if you want 32-bit data, use 32-bit integers.
If you want 64-bit data, use 64-bit integers. There is virtually no
situation where 64-bit integers are faster than 32-bit integers on a
64-bit processor. On such rare occasions when there *is* a difference,
coding specifically for the algorithm in question will make more difference.
 
S

Skybuck Flying

MooseFET said:
That is simply false. Why do you think it can't be done with virtual
methods?

Because virtual methods is not operator overloading.

Writing code such as:

Div( Multiply( Add( A, B ), C ), D )

Is unpractical and ofcourse slow, ^^^ call overhead.
Virtual methods when done the way that Borland Pascal, Delphi and a
good implementation of C++ add very little extra time to the total run
time. The virtual method dispatch code takes less instructions than
the entry code of most routines.

A good operator overloading implementation does not even have call overhead.

I think that's how Delphi's operator overloading for records work.

^^^ No overhead ^^^

(Not sure though, but I thought that's how it works)

No, it don't. It only gives the appearance of doing what you want.
There is nothing scalable going on.

Apperently you see it differently.

I already used these techniques to scale to infinety.

So you simply wrong about that one.

Bye,
Skybuck.
 
S

Skybuck Flying

What makes you believe I don't get it ?

Please stop your unnecessary insults.

Bye,
Skybuck.
 
S

Skybuck Flying

Absolutely nonsense.

If I want I can write a computer program that runs 32 bit when possible and
64 bit emulated when needed.

My computer program will outperform your "always 64 emulated" program WITH
EASE.

The only problem is that I have to write each code twice.

A 32 bit version and a 64 bit version.

I simply instantiate the necessary object and run it.

Absolutely no big deal.

The only undesirable property of this solution is two code bases.

Your lack fo programming language knownledge and experience is definetly
showing.

Bye,
Skybuck.
 
S

Skybuck Flying

Math was accident, probably related anyway.

Electronics.design might be related as well ;)

Bye,
Skybuck.
 
S

Skybuck Flying

There is definetly a speed difference especially for mul and div for the
modes I described.

Why do I have to choose the data type ?

Why can't the program choose the data type at runtime ?

Bye,
Skybuck.
 
D

David Brown

Skybuck said:
There is definetly a speed difference especially for mul and div for the
modes I described.

Why do I have to choose the data type ?

Why can't the program choose the data type at runtime ?

If *you* are writing the program, *you* should know what sort of data is
stored in each variable. *You* can then tell the compiler by choosing
an appropriate data type. Is that so hard to grasp? It is up to *you*
to figure out that what limits there will be on the size of the data you
are using, and therefore pick 32-bit or 64-bit (or whatever) integers
for your program. If you think there could be large variations in the
sizes, then either use a data type that will certainly be big enough, or
pick one with no arbitrary limit (there are multiple precision integer
libraries available for most languages), or use a dynamically typed
language.
 
D

David Brown

Skybuck said:
Because virtual methods is not operator overloading.

Writing code such as:

Div( Multiply( Add( A, B ), C ), D )

Is unpractical and ofcourse slow, ^^^ call overhead.


A good operator overloading implementation does not even have call overhead.

I think that's how Delphi's operator overloading for records work.

^^^ No overhead ^^^

(Not sure though, but I thought that's how it works)



Apperently you see it differently.

I already used these techniques to scale to infinety.

So you simply wrong about that one.

Bye,
Skybuck.

When you are looking at operator overloading, the compiler sees an
expression such as "b * c", it considers it *exactly* the same as a
function "multiply(a, b)". There is absolutely no difference to the
compiler, and you can use virtual methods, overloading, inlining, and
any other tricks to get the effect you want.

I presume you also know that compilers do not have to use virtual calls
just because a function is a virtual method of a class? If the compiler
knows what class an object is, then it can short-circuit the virtual
method table and call the method directly. And if it knows the
definition of the method in question, it can automatically inline the
call - resulting in zero overhead.
 
S

Skybuck Flying

David Brown said:
If *you* are writing the program, *you* should know what sort of data is
stored in each variable. *You* can then tell the compiler by choosing an
appropriate data type. Is that so hard to grasp? It is up to *you* to
figure out that what limits there will be on the size of the data you are
using, and therefore pick 32-bit or 64-bit (or whatever) integers for your
program. If you think there could be large variations in the sizes, then
either use a data type that will certainly be big enough, or pick one with
no arbitrary limit (there are multiple precision integer libraries
available for most languages), or use a dynamically typed language.

Well that clearly sucks.

The world is not completely 64 bit, The world is not statis it fluctuates.

Sometimes the program only needs 32 bits, sometimes 64 bits.

Always choosing 64 bits would hurt performance LOL.

Bye,
Skybuck.
 
S

Skybuck Flying

Which is ofcourse impossible.

The compiler does not know what the program wants at compile time.

Does it want 32 bit or 64 bit ?

Only the program knows at runtime !

Depends on the situation.

Bye,
Skybuck.
 
M

MooseFET

Because virtual methods is not operator overloading.

Any operator overloading that allows the type of the variable to be
determined at run time most certainly is virtual methods. You need to
look into how it is done.

Operator overloading that is not virtual (ei: the variable type can't
be changed at run time) can be inlined. A smart compiler will do this
for small functions.
Writing code such as:

Div( Multiply( Add( A, B ), C ), D )

Is unpractical and ofcourse slow, ^^^ call overhead.

There is nothing unpractical about what you coded. People write code
like that all the time.

A good operator overloading implementation does not even have call overhead.

A non-virtual function can be inlined.
I think that's how Delphi's operator overloading for records work.

^^^ No overhead ^^^

(Not sure though, but I thought that's how it works)

Why don't you know? Go read up on it. You will find out that a lot
of what you are assumeing is wrong.

Apperently you see it differently.

I already used these techniques to scale to infinety.

So you simply wrong about that one.

No you are the one who is wrong. You are suggesting that there is run
time type determination that is different from the virtual method
dispatch. This is simply false. Get your compiler to spit out the
assembly and look at it. You will see what it really does.
 
M

MooseFET

Absolutely nonsense.

If I want I can write a computer program that runs 32 bit when possible and
64 bit emulated when needed.

My computer program will outperform your "always 64 emulated" program WITH
EASE.

The only problem is that I have to write each code twice.

This statement is incorrect. C, C++, Borland Pascal and it
decendants, and just about every other language I can think of allow
you to declare a new type to be the same as a simple type, allow
conditional compiles, and allow include files. You don't need to have
two copies of the source code.
A 32 bit version and a 64 bit version.

I simply instantiate the necessary object and run it.

Absolutely no big deal.

The only undesirable property of this solution is two code bases.

Your lack fo programming language knownledge and experience is definetly
showing.

Right back at you.
 
R

Ron Natalie

MooseFET said:
This statement is incorrect. C, C++, Borland Pascal and it
decendants, and just about every other language I can think of allow
you to declare a new type to be the same as a simple type, allow
conditional compiles, and allow include files. You don't need to have
two copies of the source code.

Incorrect. C and C++ certainly do not. You can #define or typedef
something that appears to be a type but they aren't distinct types.
You're just conditionally compiling which type you are using (which
accomplishes what you want). The distinction is an important one.
A typedef isn't seperately resolvable from the type it aliases.

All that being said, we have produced versions of our product for
a wide variety of machines in C++ and C and to this day provide
win 32 and 64 versions. The difference in code is a handful of
conditional compiles and typedefs. We spend more time dealing
with interfaces to other people's products (ESPECIALLY FREAKING
MICROSOFT) who haven't bothered to provide 64-bit versions of
all their interfaces.
 
D

David Brown

Skybuck said:
Well that clearly sucks.

The world is not completely 64 bit, The world is not statis it fluctuates.

Sometimes the program only needs 32 bits, sometimes 64 bits.

Always choosing 64 bits would hurt performance LOL.

So if your program needs 32 bits, use 32 bits. If it needs 64 bits, use
64 bits.

I work in the world of embedded systems - it can often make a huge
difference whether you pick 8 bits, 16 bits, or 32 bits for your data.
People sometimes prefer 24 bits or 40 bits - whatever makes sense for
the task in question. This all makes far more of a difference than a
choice of 32-bit or 64-bit integers (on a 32-bit or 64-bit processor),
yet programmers have no trouble dealing with it.

If you are trying to get performance, figure out how to use libraries
written by experts, rather than trying to roll your own code at this
level - you haven't a chance of getting optimal code until you first
understand what you want your program to do, and then understand the
issues that actually make a difference in real life programming rather
than some little test snippet of code.
 
D

David Brown

Skybuck said:
Which is ofcourse impossible.

The compiler does not know what the program wants at compile time.

Does it want 32 bit or 64 bit ?

Only the program knows at runtime !

Depends on the situation.

Bye,
Skybuck.

If you learn to use Usenet properly before trying to post this stuff, it
would be a lot easier to get you back on the path of sane software
development. It's not worth spending time answering you if you can't
write questions or comments that make sense.
 
L

LR

Skybuck said:
Which is ofcourse impossible.

I think you snipped a little too much context. Just MHO but leaving the
context, or at least a little of it would be much better. TIA.
The compiler does not know what the program wants at compile time.

I think it would be safe to say that I don't understand the above.
Besides, it's not really the compiler's job to know what the "program"
wants. The "program" doesn't really want anything. It's what the
programmer wants. Or what whomever is paying the programmer wants. Isn't
it? Or am I mistaken about that?



Does it want 32 bit or 64 bit ?

Only the programmer knows for sure.

Only the program knows at runtime !

Please tell us how the program "knows" this at run time or any other
time for that matter.
Depends on the situation.

How?


I suspect that what I think you want, if I understand correctly, is
possible, but the overhead at run time makes it uneconomical.


Just consider the situation where a user will input an array of numbers.
You, the programmer, will not know in advance what the magnitude of
the numbers will be. Nor will the program "know" in advance. But
suppose you or the program could know (for some meaning of the word
know) that.

How would you store the array?

All elements the same size or each element a different size depending on
the magnitude of the number stored in that element?

Of course, if you want, you could make your array some sort of
polymorphic container. Sounds expensive.

Of course, there are some implementations of code for numbers that can
have a huge amount of precision and/or magnitude where the amount of
data used for each number can vary quite a bit, but these are for fairly
specialized cases and usually not very efficient in using time or space.

The general moral here is, if your data set requires information in
units of light years don't input your data in angstroms.

OTOH, I once heard someone suggest that a particular implementation of
an interpreted language I once used was implemented in this way to store
numbers that could fit into a 16 bit integer as 16 bit integers and
everything else as a 64 bit real type.

Maybe, if you're really interested, you might think about how to do that
simple case.

LR
 
D

David Brown

Ron said:
Incorrect. C and C++ certainly do not. You can #define or typedef
something that appears to be a type but they aren't distinct types.

You are correct that C and C++ do not distinguish between two types that
are typedef'ed the same (and obviously not if they are #define'd). In
other words, if typeA and typeB are both typedef'ed to "int", then it is
perfectly legal to assign data of typeA to a variable of typeB.

However, it is possible to use C++ classes to get much of the effect of
this. You would first have to make a base class type such as
"baseInt32" with a single 32-bit integer data member, and a full range
of operators and constructors to allow it to act like a normal integer -
if these are all inlined simple functions, then code should be optimised
properly (although you might not get as good constant folding as with a
normal int). If you then have two types that directly inherit from
"baseInt32", you'll have two types that function are identical in
function with each other, pretty close to identical in function to the
original int, and which are mutually incompatible for things like
assignment. It's far from perfect, and more than a little messy, but it
could give you much the same effect as proper strongly-typed subtyping.
 
N

nospam

I hope that this doesn't sound impolite, but why are you posting to
sci.electronics.design and alt.math?

Because he is a complete loon and don't worry about being impolite his
previous widely cross posted rantings have already earned him many impolite
suggestions. Kill file him and ignore this thread - job done.
--
 
T

Torrey Hills

That's why I told you that checking for whether emulation is needed and
picking a code path will be slower than just using it all the time. The
cost of emulation, unless you're writing incredibly math-intensive code, is
trivial. If you care about raw math performance and the code is just too
slow to use, buying a faster CPU will be cheaper than trying to figure out
how to make slow machines perform better. It's certainly cheaper than
modifying the ISA.

S

Wow, wonderful discussion. Learned so much.

Ken


Opportunities are never lost. The other fellow takes those you miss.


| Torrey Hills Technologies, LLC |
| www.threerollmill.com |
| www.torreyhillstech.com |
 
Top