c# - 当我将 c++ DLL(我从 c# 调用)重建为/CLR(最初是 native 的)时,性能下降了一半

标签 c# c++ dll visual-studio-2013

当我将 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/

相关文章:

java - Cassandra -f 找不到依赖库 java.lang.UnsatisfiedLinkError

c - 使用 MSVC 编译时,程序如何调用未修饰的 stdcall DLL 导出?

c# - ExpandoObject 的动态 LINQ 查询?

c# - 如何枚举 NVMe (M2) 驱动器并在 c# 中获取它们的温度?

c# - 读取 XML 文件并创建与 XML 内容匹配的对象列表

c++ - 请求从 ‘std::vector<AdjacencyData> (*)()’ 到非标量类型 ‘std::vector<AdjacencyData>’ 的转换

c# - 为什么我的 C# 应用程序无法加载我的 C++ dll?

c# - SelectSingleNode 和命名空间 - 找不到节点(使用命名空间 mgr)

c++ - 用C++读取音频

c++ - 命名空间与命名约定