Operator Performance

S

Stephan Rose

Still been beating on my Multi Unit Scalar structure and...it's coming
along well. Since it is a core component of my app that virtually
everything builds on, even the smalles amount of performance gain is
worth it.

But I think I have hit a wall.

One million operations now average around 98ms give or take. If it's
Power 0/1 (linear unit) or Power 2+ (area, volume, etc) unit makes no
measurable difference. The additional loop makes less difference in
performance than planetary alignment. (Code is below sig for those who
wanna check it out).

So just out of boredom and because I have nothing better to do, I went
and measured the raw time the operator takes.

Namely:

public static Scalar operator + (Scalar a, Scalar b)
{
return new Scalar();
}

Result: average around 40ms!!

Wait a sec...I am spending almost half my time just in overhead for
the operator? I am betting another good portion goes to the call to
the conversion function. Making my bottom line that the operator
overhead itself is taking magnitudes more time than the actual
operation being performed.

So my question comes here: Is there anything I can do to reduce the
raw overhead of the operator itself? Compiler flag? option? attribute?
virgin sacrifice to bill gates?

Thoughts and suggestions would be very welcome!!

Thanks,

--
Stephan
2003 Yamaha R6

kimi no koto omoidasu hi
nante nai no wa
kimi no koto wasureta toki ga nai kara


public static Scalar operator + (Scalar a, Scalar b)
{
if (a.Power != b.Power) throw new
System.InvalidOperationException("Operator+pow");

switch(a.Unit)
{
case ScalarUnit.Centimeter:
return new Scalar(a.Value +
b.GetCentimeterValue(), ScalarUnit.Centimeter, a.Power);
case ScalarUnit.Inch:
return new Scalar(a.Value + b.GetInchValue(),
ScalarUnit.Inch, a.Power);
case ScalarUnit.Mil:
return new Scalar(a.Value + b.GetMilValue(),
ScalarUnit.Mil, a.Power);
case ScalarUnit.Millimeter:
return new Scalar(a.Value +
b.GetMillimeterValue(), ScalarUnit.Millimeter, a.Power);
case ScalarUnit.Degree:
return new Scalar(a.Value +
b.GetDegreeValue(), ScalarUnit.Degree, a.Power);
case ScalarUnit.Radian:
return new Scalar(a.Value +
b.GetRadianValue(), ScalarUnit.Radian, a.Power);
default:
throw new
System.InvalidOperationException("Operator+");
}
}


public double GetMillimeterValue()
{
double scale;
switch (this.Unit)
{
case ScalarUnit.Centimeter:
scale = 10.0;
break;
case ScalarUnit.Inch:
scale = 25.4;
break;
case ScalarUnit.Mil:
scale = 0.0254;
break;
case ScalarUnit.Millimeter:
return Value;
default:
throw new
System.InvalidOperationException("Cannot convert unit.");
}

if (Power > 0)
{
int p = Power - 1;

while (p-- != 0)
{
scale *= scale;
}

return Value * scale;
}

return Value * scale;
}
 
B

Barry Kelly

Stephan Rose said:
Still been beating on my Multi Unit Scalar structure and...it's coming
along well. Since it is a core component of my app that virtually
everything builds on, even the smalles amount of performance gain is
worth it.

But I think I have hit a wall. [...]
So my question comes here: Is there anything I can do to reduce the
raw overhead of the operator itself? Compiler flag? option? attribute?
virgin sacrifice to bill gates?

The operator is translated directly into a static method call. So, your
problem would appear to be that static method call with struct
parameters is too expensive. There are two alternatives:

1) Use a reference class instead of a struct. (This is only slightly
faster due to overhead of GC.)

2) Use a static method which accepts ref and out parameters rather than
relying on copying. E.g.:

public static void Add(out Scalar result, ref Scalar left,
ref Scalar right)

Both of these are faster to call than a static method relying on copies,
where the body simply returns an empty Scalar, for a Scalar containing 1
double, 1 integer and 1 enumeration value.

Don't forget that the more complex your method becomes, the less likely
the JIT compiler is to inline it.

-- Barry
 
S

Stephan Rose

Stephan Rose said:
Still been beating on my Multi Unit Scalar structure and...it's coming
along well. Since it is a core component of my app that virtually
everything builds on, even the smalles amount of performance gain is
worth it.

But I think I have hit a wall. [...]
So my question comes here: Is there anything I can do to reduce the
raw overhead of the operator itself? Compiler flag? option? attribute?
virgin sacrifice to bill gates?

The operator is translated directly into a static method call. So, your
problem would appear to be that static method call with struct
parameters is too expensive. There are two alternatives:

1) Use a reference class instead of a struct. (This is only slightly
faster due to overhead of GC.)

2) Use a static method which accepts ref and out parameters rather than
relying on copying. E.g.:

public static void Add(out Scalar result, ref Scalar left,
ref Scalar right)

Both of these are faster to call than a static method relying on copies,
where the body simply returns an empty Scalar, for a Scalar containing 1
double, 1 integer and 1 enumeration value.

Don't forget that the more complex your method becomes, the less likely
the JIT compiler is to inline it.

-- Barry

Thanks for your input there, that helped big time. The C++ version
still blows it away (1.6ms VS 22ms for the identical # of operations)
but...I guess there is nothing further I can do performance-wise.

I am sure as the framework matures over the next years things like
that will speed up.

--
Stephan
2003 Yamaha R6

kimi no koto omoidasu hi
nante nai no wa
kimi no koto wasureta toki ga nai kara
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top