November 08, 2007
downs wrote:
> I've tried to translate the attached C++ program to D (D program also
> attached).
> 
> Even after explicitly using the __builtin_sqrt (which correctly
> generates a fsqrt instruction (shame on you, non-inlined std.math)), the
> D code is significantly slower (12.9s for D vs 9s for C++).
> 
> Does anybody know why this is so?
>  --downs, confused and saddened
> 
> PS: benchmark
> 
> gentoo-pc ~/d/RayBen $ gdc ray1.d -O3 -frelease -ffast-math -o ray1_d
> tools/base.d && time ./ray1_d >result_d.pnm; g++ ray1.cxx -O3
> -ffast-math -o ray1_cpp && time ./ray1_cpp > result_cxx.pnm
> 
> real    0m13.448s
> user    0m12.730s
> sys     0m0.090s
> 
> real    0m10.128s
> user    0m9.810s
> sys     0m0.020s
> 

Could the difference be in part due to default initialization in D? Maybe all your rays and vecs are getting initialized first to NaN and then overwritten with the value you want, and that is slowing it down.

You could try sticking some =void's in your structs, like so:

struct Vec {
  double x=void, y=void, z=void;
  Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); }
  Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); }
  Vec opMul(double a) { return Vec(x*a, y*a, z*a); }
  double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; }
  Vec unitise() { return opMul(1.0/dsqrt(dot(*this))); }
}

struct Pair(T, U) { T first=void; U second=void; }
typedef Pair!(double, Vec) Hit;

struct Ray { Vec orig=void, dir=void; }


--bb
November 09, 2007
Bill Baxter wrote:
> 
> Could the difference be in part due to default initialization in D? Maybe all your rays and vecs are getting initialized first to NaN and then overwritten with the value you want, and that is slowing it down.
> 
> You could try sticking some =void's in your structs, like so:
> 
> struct Vec {
>   double x=void, y=void, z=void;
>   Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); }
>   Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); }
>   Vec opMul(double a) { return Vec(x*a, y*a, z*a); }
>   double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; }
>   Vec unitise() { return opMul(1.0/dsqrt(dot(*this))); }
> }
> 
> struct Pair(T, U) { T first=void; U second=void; }
> typedef Pair!(double, Vec) Hit;
> 
> struct Ray { Vec orig=void, dir=void; }
> 
> 
> --bb

If you check the source, you'll see that practically all my structs are either
manually initialized with proper values or the result of a calculation. Also,
I tried that and it's not it.
Sorry.

Still, thanks for the idea!
 --downs
November 10, 2007
Any success? If you find out what it was could you post it?

The only things I can think of are a stack heap allocation, variable
initialisation and better optimization differences...
Maybe making some smaller test cases.



November 10, 2007
"downs" <default_357-line@yahoo.de> wrote in message news:fh0iem$2dhc$1@digitalmars.com...
> Bill Baxter wrote:
>>
>> Could the difference be in part due to default initialization in D?
>> Maybe all your rays and vecs are getting initialized first to NaN and
>> then overwritten with the value you want, and that is slowing it down.
>>
>> You could try sticking some =void's in your structs, like so:
>>
>> struct Vec {
>>   double x=void, y=void, z=void;
>>   Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); }
>>   Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); }
>>   Vec opMul(double a) { return Vec(x*a, y*a, z*a); }
>>   double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; }
>>   Vec unitise() { return opMul(1.0/dsqrt(dot(*this))); }
>> }
>>
>> struct Pair(T, U) { T first=void; U second=void; }
>> typedef Pair!(double, Vec) Hit;
>>
>> struct Ray { Vec orig=void, dir=void; }
>>
>>
>> --bb
>
> If you check the source, you'll see that practically all my structs are either
> manually initialized with proper values or the result of a calculation. Also,
> I tried that and it's not it.
> Sorry.
>
> Still, thanks for the idea!
> --downs

Sorry if this has already been discussed, but if not: Have you checked to
see if function inlining differences are the culprit? The D front-end
doesn't inline functions with byref params, and for DMD at least the FE is
responsible for all inlining.

For GDC the front-end inlining might be turned off anyhow (I can't
remember), and maybe GCC does all that in the intermediate or backend
stages.. If so it would presumably be pretty close to the same for D and C++
but it might be worth a look anyhow.

1 2
Next ›   Last »