3

我正在为 C# 编写一个 DLL 作为高性能模块,所以我使用 C++/CLI,因为它很容易在 C# 中引用并支持本机代码。我在msdn上发现使用 #pragma managed(push, off) 和 #pragma managed(pop) 可以将其中的代码编译为本机代码。但根据我的简单测试,结果显示相反。

这是使用 Visual Studio 2012 使用 /clr 编译的代码。

int clrloop()
{
  for (int i = 0; i < 999999999; i++)
  {
      double test=9.999;
      test=pow(test, 10);
  }
  return 0;
}

#pragma managed(push,off)
int loop()
{
  for (int i = 0; i < 999999999; i++)
  {
      double test=9.999;
      test=pow(test, 10);
  }
  return 0;
}
#pragma managed(pop)

int main(array<System::String ^> ^args)
{
    int a=loop();
    int b=clrloop();
    return 0;
}

性能分析表明,非托管 loop() 的成本是 clrloop() 的两倍。但是,如果我将 loop() 放入不同的 .cpp 文件并设置这个使用 /clr 编译的单个文件,并且不使用任何 #pragma managed(push, off) 东西,结果就像预期的那样好。

那么,这个#pragma 有什么问题?

4

2 回答 2

6

我自己找到答案,所以,我正在回答它。

问题是由函数 pow() 引起的。

pow() 所在的math.h只是简单地包含在没有任何预处理器指令的情况下,这意味着它只是作为托管编译的。所以非托管循环()将不得不调用托管pow(),从而成为从托管main()到非托管循环(),再到托管pow()的三级跳转,并导致开销。解决方案是将math.h包含在#pragma managed(push, off) 和#pragma managed(pop) 中。

于 2013-03-22T08:41:58.803 回答
0

maverix3 的答案的补充:

您应该使用非托管函数并将其放置在不使用预编译头文件的单独 CPP 文件中,以便手动将所有头文件包含在 #pragma managed(push,off) 部分中。然后添加一个头文件并记住在函数定义周围添加相同的 pragma 包装器。

于 2016-03-31T01:11:31.847 回答