gpt4 book ai didi

c# - 在 C++ 中编写性能关键的 C# 代码

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:11:48 25 4
gpt4 key购买 nike

我目前正在处理一些对性能至关重要的代码,我有一个特殊的情况,我喜欢用 C# 编写整个应用程序,但性能原因意味着 C++ 最终要快得多。

我对某些代码的两种不同实现方式(一种使用 C#,另一种使用 C++)进行了一些基准测试,时间显示 C++ 版本快 8 倍,两个版本都处于 Release模式并且启用了所有优化。 (实际上,C# 有被编译为 64 位的优势。我忘记在 C++ 时序中启用它)

所以我想,我可以用 C# 编写大部分代码库(C# 使编写起来非常容易),然后编写性能至关重要的东西的 native 版本。我在 C# 和 C++ 中测试的特定代码片段是花费了 > 95% 的处理时间的关键区域之一。

不过,在这里编写 native 代码的推荐智慧是什么?我从未编写过调用 native C++ 的 C# 应用程序,所以我不知道该怎么做。我想以一种尽可能减少必须进行 native 调用的成本的方式来执行此操作。

谢谢!

编辑:下面是我实际尝试处理的大部分代码。它用于 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);
}

以上只是我实际正在处理的大型应用程序的最低要求。还有更多的事情正在发生,但是对性能最关键的事情发生在这三个函数中。我知道成对函数很慢(它是 n^2),而且我确实有其他更快的方法(其中一个是 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 类,它的工作方式就像一个常规的数学 vector ,为简洁起见我不包括在内。

最佳答案

您需要与 native 代码进行交互。你可以把它放在一个 DLL 中并调用。好的,当您不经常转换并且界面很薄时。最灵活和最快速的解决方案是用 C++/CLI 语言编写一个 ref 类包装器。看看this magazine article进行介绍。

最后但同样重要的是,您真的应该分析 C# 代码。 8 倍是相当过分的。在您至少了解它为什么这么慢之前,请不要开始这样做。您不想在 C++ 代码中重现原因,那样会毁掉一周的工作。

谨防错误的直觉。 64 位代码实际上并不更快,它通常比 x86 代码慢一点。它有一堆额外的寄存器,非常不错。但是所有指针的大小都是原来的两倍,而且你不会得到双倍的 cpu 缓存。.

关于c# - 在 C++ 中编写性能关键的 C# 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5607920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com