C# 用C+编写性能关键的C代码+; 我目前正在研究一些性能关键代码,我有一个特殊的情况,我喜欢在C语言中编写整个应用程序,但是性能的原因意味着C++的速度快得多。p> 我对两种不同的代码实现了一些基准(一种是C,另一种是C++),计时显示C++版本是8倍,两种版本都是发布模式,所有优化都是启用的。(实际上,C语言的优点是编译为64位。我忘记在C++定时启用这个)
所以我想,我可以用C#编写大部分代码库(C#使得编写非常容易),然后编写性能至关重要的本地版本。在C和C++中测试的特定代码块是处理时间超过95%的关键区域之一。 但是,在这里编写本机代码的建议智慧是什么?我从来没有写过一个调用C++的C++应用程序,所以我不知道该怎么做。我想以一种尽可能降低本机调用成本的方式来实现这一点 谢谢 编辑:下面是我实际要处理的大部分代码。这是一个n体模拟。95-99%的CPU时间将花费在Body.Pairwise()中 我还有一个类,它仅通过以下方法驱动模拟:C# 用C+编写性能关键的C代码+; 我目前正在研究一些性能关键代码,我有一个特殊的情况,我喜欢在C语言中编写整个应用程序,但是性能的原因意味着C++的速度快得多。p> 我对两种不同的代码实现了一些基准(一种是C,另一种是C++),计时显示C++版本是8倍,两种版本都是发布模式,所有优化都是启用的。(实际上,C语言的优点是编译为64位。我忘记在C++定时启用这个),c#,c++,performance,C#,C++,Performance,所以我想,我可以用C#编写大部分代码库(C#使得编写非常容易),然后编写性能至关重要的本地版本。在C和C++中测试的特定代码块是处理时间超过95%的关键区域之一。 但是,在这里编写本机代码的建议智慧是什么?我从来没有写过一个调用C++的C++应用程序,所以我不知道该怎么做。我想以一种尽可能降低本机调用成本的方式来实现这一点 谢谢 编辑:下面是我实际要处理的大部分代码。这是一个n体模拟。95-99%的CPU时间将花费在Body.Pairwise()中 我还有一个类,它仅通过以下方法驱动模拟:
public static void Pairwise(Body[] b, int n)
{
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
b[i].Pairwise(b[j]);
}
public static void Predict(Body[] b, int n, double dt)
{
for (int i = 0; i < n; i++)
b[i].Predict(dt);
}
public static void Correct(Body[] b, int n, double dt)
{
for (int i = 0; i < n; i++)
b[i].Correct(dt);
}
publicstaticvoid成对(Body[]b,int-n)
{
对于(int i=0;i
主循环看起来就像:
for (int s = 0; s < steps; s++)
{
Predict(bodies, n, dt);
Pairwise(bodies, n);
Correct(bodies, n, dt);
}
for(int s=0;s
以上只是我实际正在开发的一个更大应用程序的最低要求。还有一些事情要做,但最关键的性能问题出现在这三个函数中。我知道成对函数的速度很慢(它是n^2),我也有其他更快的方法(Barnes hutt为一个,它是n logn),但这超出了我在这个问题中所要求的范围
<> > C++代码几乎相同:
struct Body
{
public:
double Mass;
Vector Position;
Vector Velocity;
Vector Acceleration;
void Pairwise(Body &b)
{
Vector dr = b.Position - this->Position;
double r2 = dr.LengthSq();
double r3i = 1 / (r2 * sqrt(r2));
Vector da = r3i * dr;
this->Acceleration += (b.Mass * da);
b.Acceleration -= (this->Mass * da);
}
void Predict(double dt)
{
Velocity += (0.5 * dt) * Acceleration;
Position += dt * Velocity;
}
void Correct(double dt)
{
Velocity += (0.5 * dt) * Acceleration;
Acceleration.Clear();
}
};
void Pairwise(Body *b, int n)
{
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
b[i].Pairwise(b[j]);
}
void Predict(Body *b, int n, double dt)
{
for (int i = 0; i < n; i++)
b[i].Predict(dt);
}
void Correct(Body *b, int n, double dt)
{
for (int i = 0; i < n; i++)
b[i].Correct(dt);
}
结构体
{
公众:
双质量;
矢量位置;
矢量速度;
矢量加速度;
空位成对(主体和b)
{
向量dr=b.位置-此->位置;
双r2=dr.LengthSq();
双r3i=1/(r2*sqrt(r2));
向量da=r3i*dr;
此->加速度+=(b.质量*da);
b、 加速度-=(此->质量*da);
}
空隙预测(双dt)
{
速度+=(0.5*dt)*加速度;
位置+=dt*速度;
}
无效正确(双dt)
{
速度+=(0.5*dt)*加速度;
加速度。清除();
}
};
成对无效(主体*b,内部n)
{
对于(int i=0;i
主回路:
for (int s = 0; s < steps; s++)
{
Predict(bodies, n, dt);
Pairwise(bodies, n);
Correct(bodies, n, dt);
}
for(int s=0;s
还有一个Vector类,它的工作原理与常规数学向量类似,为了简洁起见,我不包括它。您需要与本机代码进行接口。您可以将其放入DLL和pinvoke中。好的,当你不经常转换并且界面很薄的时候。最灵活、最快速的解决方案是用C++/CLI语言编写ref类包装器。请看下面的介绍 最后但并非最不重要的一点是,您确实应该分析C代码。系数8是相当过分的。在你至少对它为什么这么慢有半个概念之前,不要开始这样做。你不想在C++代码中重新考虑原因,这会毁掉一周的工作。 小心错误的直觉。64位代码实际上并不快,它通常比x86代码慢一点。它有一堆额外的寄存器,非常好。但是所有指针的大小都是原来的两倍,而且cpu缓存也不会增加一倍。
最简单的方法是创建C++ ActiveX DLL。 然后您可以在C#项目中引用它们,VisualStudio将创建用于包装ActiveX COM对象的互操作
您可以使用互操作代码,如C#代码,而无需额外的包装代码 有关AciveX/C#的更多信息:您有两种选择:p/Invoking和C++/CLI p/调用 通过使用p/javek或平台调用,.NET(因此C语言)可以调用非托管代码(C++代码)。它可能有点压倒一切,但是绝对有可能让你的C代码调用到性能关键的C++代码。 一些MSDN链接可帮助您入门:
DllImportAttribute
将该函数导入C#
例如,您有一个C++项目,创建一个具有以下功能的MunKi.dLL:
extern "C" __declspec(dllexport) void FastMonkey();
然后在C#中定义如下:
class NativeMethods
{
[DllImport("Monkey.dll", CallingConvention=CallingConvention.CDecl)]
public static extern void FastMonkey();
}
您可以调用Cype中的C++函数,调用<代码> NATEVIEMEDSOD。 一些常见的问题和注意事项:
- 花时间学习互操作封送。理解这一点将大大有助于创建正确的P/调用定义
- 默认ca
class NativeMethods { [DllImport("Monkey.dll", CallingConvention=CallingConvention.CDecl)] public static extern void FastMonkey(); }
Vector dr = b.Position - this.Position; ... Vector da = r3i * dr; this.Acceleration += (b.Mass * da); b.Acceleration -= (this.Mass * da);