Pro*_*ish 12 .net c c# performance
我有一个非常大的嵌套for循环,其中对浮点数执行一些乘法和加法.
for (int i = 0; i < length1; i++)
{
double aa = 0;
for(int h = 0; h < 10; h++)
{
aa += omega[i][outsideGeneratedAddress[h]];
}
double alphaOld = alpha;
alpha = Math.Sqrt(alpha * alpha + aa * aa);
s = -aa / alpha;
c = alphaOld / alpha;
for(int j = 0; j <= i; j++)
{
double oldU = u[j];
u[j] = c * oldU + s * omega[i][j];
omega[i][j] = c * omega[i][j] - s * oldU;
}
}
Run Code Online (Sandbox Code Playgroud)
这个循环占用了我的大部分处理时间,并且是一个瓶颈.
如果我在C中重写这个循环并从C#接口,我是否可能看到任何速度改进?
编辑:我更新了代码,以显示如何生成s和c.内部循环实际上从0到i,尽管它可能对问题没有太大影响
EDIT2:我在VC++中实现了算法并通过dll将其与C#相关联,并且在启用所有优化后,C#的速度提升了28%.启用SSE2的参数特别有效.使用MinGW和gcc4.4进行编译只能提高15%的速度.刚尝试了英特尔编译器,该代码的速度提升了49%.
更新:
如果你编写内部循环来考虑引用的位置会发生什么:
for (int i = 0; i < length1; i++)
{
s = GetS(i);
c = GetC(i);
double[] omegaTemp = omega[i];
for(int j = 0; j < length2; j++)
{
double oldU = u[j];
u[j] = c * oldU + s * omegaTemp[j];
omegaTemp[j] = c * omegaTemp[j] - s * oldU;
}
}
Run Code Online (Sandbox Code Playgroud)
使用unsafe
块和指针索引到您的omega
数组.这将消除范围检查的开销,如果您进行了足够的访问,则可能是一个重要的胜利.很多时间也可能花在你GetS()
和GetC()
你没有提供源代码的功能上.
虽然大多数其他答案倾向于建议您研究 C# 解决方案,但大多数都忽略了一点:如果您使用良好的优化编译器,此方法的 C 代码会更快(我建议 Intel,对于此类代码非常有效) )。
编译器还将节省一些 JIT 工作,并产生更好的编译输出(甚至 MSVC 编译器也可以生成 SSE2 指令)。默认情况下不会检查数组边界,可能会展开一些循环,总而言之,您可能会看到性能的显着提升。
正如已经正确指出的那样,调用本机代码可能会产生一些开销;然而,如果 length1 足够大,与加速相比,这应该是微不足道的。
您可能肯定会将此代码保留在 C# 中,但请记住,与几个 C 编译器相比,CLR(就像我所知道的所有其他 VM 一样)对优化生成的代码几乎没有作用。