我目前正在编写一些性能关键代码,有一个特殊情况,我想用C#编写整个应用程序,但是由于性能原因,C++的速度比C#快得多。
我对两个不同实现的代码(一个是C#,另一个是C ++)进行了基准测试,计时显示C ++版本要快8倍,两个版本都是在发布模式下并启用了所有优化。(实际上,C#被编译为64位。我忘记在C++计时中启用这一点)
所以我想,我可以用C#编写大部分代码库(C#很容易编写),然后在性能关键的地方编写本机代码。我测试了C#和C ++中的特定代码段,这是处理时间超过95%的关键区域之一。
然而,如何编写本机代码呢?我从未编写过调用本机C ++的C#应用程序,所以我不知道该怎么做。我想尽可能以最小化调用本机代码的成本方式进行。
谢谢!
编辑:以下是我真正要处理的大部分代码。它用于n体模拟。 95-99%的CPU时间将在Body.Pairwise()中花费。
class Body
{
public double Mass;
public Vector Position;
public Vector Velocity;
public Vector Acceleration;
// snip
public void Pairwise(Body b)
{
Vector dr = b.Position - this.Position;
double r2 = dr.LengthSq();
double r3i = 1 / (r2 * Math.Sqrt(r2));
Vector da = r3i * dr;
this.Acceleration += (b.Mass * da);
b.Acceleration -= (this.Mass * da);
}
public void Predict(double dt)
{
Velocity += (0.5 * dt) * Acceleration;
Position += dt * Velocity;
}
public void Correct(double dt)
{
Velocity += (0.5 * dt) * Acceleration;
Acceleration.Clear();
}
}
我还有一个类专门驱动模拟器,具有以下方法:
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);
}
主循环看起来就像这样:
for (int s = 0; s < steps; s++)
{
Predict(bodies, n, dt);
Pairwise(bodies, n);
Correct(bodies, n, dt);
}
以上只是我正在开发的较大应用程序中的最低要求。有一些其他的事情正在进行,但是最关键的性能问题出现在这三个函数中。我知道pairwise函数很慢(它是n²),而且我确实有其他更快的方法(比如Barnes-hutt,它是n log n),但这超出了我在这个问题中所询问的范围。
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);
}
主循环:
for (int s = 0; s < steps; s++)
{
Predict(bodies, n, dt);
Pairwise(bodies, n);
Correct(bodies, n, dt);
}
还有一个 Vector 类,它的工作方式就像普通的数学向量,由于篇幅原因我不包括在内。