Hi,
I am new on this list. I have been interested in using .NET for numerical problems for some time.
When investigating the lower than expected performance of some code of mine, I found out that both the Microsoft JIT and the mono JIT do not inline methods with an explicit struct parameter or a struct return value.
This came as quite a shock to me, since I always assumed that structs are the way to go for performance critical stuff. I attached an example for a case that would benefit tremendously from inlining of method calls involving structs in some way.
Is there some deep philosophical reason for not inlining method calls involving structs? It does not make any sense for me, since especially in the case of small structs the opportunities for inlining and subsequent optimizations are huge.
THis would be a nice way to improve the performance of the JIT compiler by a factor of 4 or so in many cases.
This is the relevant code in mono/mini/mini.c:
---
/* fixme: why cant we inline valuetype returns? */
MONO_TYPE_ISSTRUCT (signature->ret))
return FALSE; /* its not worth to inline methods with valuetype arguments?? */
for (i = 0; i < signature->param_count; i++) {
if (MONO_TYPE_ISSTRUCT (signature->params [i])) {
return FALSE;
}
}
---Another thing I have noticed is that mono only inlines methods that are shorter than 20 bytes of IL code. I am sure that this makes sense for most applications, but in some cases it would be very useful to increase this value to 64 or maybe even 128. I think there should be a per-assembly attribute to specify the inlining threshold.
best regards
R�diger
This is a small benchmark for struct inlining: --- using System;
namespace OperatorInliningTest
{
public struct Complex
{
internal double re, im;
public Complex(double re, double im)
{
this.re = re;
this.im = im;
}
public static implicit operator Complex(double re) {
return new Complex(re, 0);
}
public static Complex I
{
get { return new Complex(0,1); }
}
public static Complex Zero
{
get { return new Complex(0,0); }
}
public static Complex One
{
get { return new Complex(1,0); }
}
public static Complex operator +(Complex a, Complex b)
{
return new Complex(a.re+b.re,a.im+b.im);
}
public static Complex operator *(Complex a, Complex b)
{
return new Complex(a.re*b.re-a.im*b.im,a.re*b.im+a.im*b.re);
}
public double AbsoluteSquared
{
get { return re*re+im*im; }
}
}
class Program
{
static int MandelbrotIteration1(Complex c)
{
Complex x = Complex.Zero;
for (int i = 0; i < 1000; i++)
{
x = x*x+c;
if (x.AbsoluteSquared > 4)
return i;
}
return -1;
}
static int MandelbrotIteration4(Complex c)
{
double xre, xim, cre, cim, t;
xre = 0; xim = 0;
cre = c.re; cim = c.im;
for (int i = 0; i < 1000; i++)
{
//x=x*x...
t = xre * xre - xim * xim;
xim = xre * xim + xre * xim;
xre = t;
//...=c;
xre += cre;
xim += cim;
//if(x.AbsoluteSquared>4)
if (xre * xre + xim * xim > 4)
return i;
}
return -1;
}
static void Main(string[] args)
{
DateTime time0, time1;
TimeSpan delta0, delta1;
Complex x=Complex.Zero;
time0 = DateTime.Now;
for (int i = 0; i < 10000; i++)
MandelbrotIteration1(x);
delta0 = DateTime.Now - time0;
time1 = DateTime.Now;
for (int i = 0; i < 10000; i++)
MandelbrotIteration4(x);
delta1 = DateTime.Now - time1;
Console.WriteLine("Relying on the JIT to inline: {0}", delta0);
Console.WriteLine("Manually inlined like in the bad old days {0}:", delta1);
Console.ReadLine();
}
}
}
_______________________________________________
Mono-list maillist - [EMAIL PROTECTED]
http://lists.ximian.com/mailman/listinfo/mono-list
