当我将 DLL 构建选项从 native 更改为/CLR 以便我可以跨 c#/c++ 边界进行调试时,我的性能降低了一半。
我开发了一个具有特定高性能算法的 native C++ DLL 来解决我的计算问题。我需要将该 DLL 插入到业务合作伙伴开发的 C# 应用程序中,并用它来替换他们性能较低的算法。一切都很顺利,我使用静态包装器调用插入了 DLL,DLL 算法运行良好,显示出比原始算法性能提高了 2 倍,但无法跨边界调试。 然后,我将 c++ DLL build设置从 native 切换到/CLR,以便能够跨 c#/c++ DLL 边界进行调试,但我的性能下降了一半。
无法弄清楚为什么会出现这种情况。
C++ DLL 端:
extern "C"
{
__declspec(dllexport) void* NewCalc()
{
return (void*)new CalcCL;
}
__declspec(dllexport) double Calc(void* sCalc, int *Buf, int Cnt)
{
return ((CalcCl*)sCalc)->Calc(Buf, Cnt);
}
}
C# 方面:
[DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int NewCalc();
[DllImport("CalcDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern double Calc(int sCalc, int[] Buf, int Cnt);
...
int sCalc = NewCalc();
...
double res;
int[] MyBuf = new int[1000];
// <Code that fills MyBuf with target data for algorithm>
res = Calc(sCalc, MyBuf, 1000);
最佳答案
对于给定的接口(interface),使用/clr 进行编译根本没有任何好处。通过右键单击主 C# 项目 > 属性 > 调试选项卡 > 勾选“启用 native 代码调试”复选框,使 native C++ 代码可调试。这同时启用了托管和非托管调试引擎。您无法单步执行 native 代码,需要在 Calc() 函数上设置断点才能实现调试引擎更改。如果设置断点很尴尬,您可能仍然喜欢用 native C++ 编写的单元测试。
您需要注意的另一件事是您在启用调试设置的情况下构建 C++ 代码。现在你明白了,这就是为什么代码看起来慢了一半。仅使用发布build设置进行性能测试,以便确保优化器已启用。最好的办法是将 native C++ 项目包含在 C# 解决方案中,以便您始终构建正确的风格。并且您必须确保将正确的 DLL 复制到 C# 主项目的构建目录中,通常通过构建后事件完成。对于调试和发布配置,该复制步骤必须不同。
请注意,[DllImport] 声明不正确。 NewCalc() 的返回类型必须是 IntPtr,因此它也适用于 64 位代码。对 C++ 代码的 64 位版本进行性能测试是您想要尝试的其他事情,如果 Calc() 函数使用 float 学,它可以提高性能。实际上,使用/clr 可以使界面变得更好,但是您必须学习如何编写 C++/CLI 代码并避免使用/clr 构建 native C++ 代码。
关于c# - 当我将 c++ DLL(我从 c# 调用)重建为/CLR(最初是 native 的)时,性能下降了一半,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55320847/