C++/CLI 性能提升
我很久以前就开始使用纯 C,然后转向 C++,现在我面对的是 C++/CLI。作为一个性能狂,我总是试图将最后一点性能压缩到每一行代码中。我目前正在进行的一个项目主要在 VB.Net 中完成(简单性、资源可用性等),但有一些对性能非常敏感的点,我计划在 C++/CLI 中完成这些部分。然而,只有一小部分可以从托管代码中取出,而其余部分则需要保持托管。问题是,与 C# 或 VB.Net 相比,编写 C++/CLI 托管函数是否可以获得任何性能提升?从我所阅读的文档中可以了解到,唯一的优点似乎是托管/非托管重击更轻。是这样吗?因为我似乎甚至无法将句柄存储在非托管数组或结构中(我可以更快地操作),例如:
String ^ mystr = "Oh, my!";
Object ^ myarray[10];
myarray[0] = mystr; // Can't event be casted to void*, int, HANDLE...
// (however, handles do have a sizeof() == 4 in Win32)
// (I don't expect the handle to behave like a pointer; just stay as handle)
I started long ago with plain C, then moved to C++ and now I'm facing C++/CLI. As a performance freak, I'm always trying to squeeze the last drop of performance to every line of code. I'm currently in a project that makes sense to be done mostly in VB.Net (simplicity, resource availability, etc.), but has a few points that are very performance sensitive and I was planning to do those parts in C++/CLI. However, only a tiny portion of it can be taken out from managed code, while the rest needs to be kept managed. The question is, is there any performance gain to be expected by writing a C++/CLI managed function comparing to C# or VB.Net? From what I could understand from the docs I've been reading, the only advantage seems to be that managed/unmanaged thunking is lighter. Is that the case? Because I can't even seem able to store handles in unmanaged arrays or structures (which I could manipulate faster), like:
String ^ mystr = "Oh, my!";
Object ^ myarray[10];
myarray[0] = mystr; // Can't event be casted to void*, int, HANDLE...
// (however, handles do have a sizeof() == 4 in Win32)
// (I don't expect the handle to behave like a pointer; just stay as handle)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
C++/CLI 是托管的 - 它被编译为与其他所有 .net 语言相同的 MSIL。如果速度对您来说至关重要,请在本机 dll 中编写关键位并从您的 vb.net 应用程序中调用它(保持 thunk 倒计时,您应该没问题)。
不过说实话,我首先分析一下代码,看看这是否真的有必要,而不仅仅是过早的优化。无论如何,MSIL 可以编译为本机代码 - 真正的问题是 .net JITer 是否与本机 c/c++ 编译器一样好。
C++/CLI is managed - it is compiled into the same MSIL as every other .net language. if speed is king for you, write the critical bit in a native dll and pinvoke it from your vb.net app (keep the thunk count down and you should be fine).
though tbh, id first profile the code to see if this is really necessary and not just premature optimisation. MSIL can be/is compiled into native code anyway - the real question is whether the .net JITer is as good as optimising as the native c/c++ compiler.
我也是一个性能狂,我了解到
在我知道性能问题出在哪里之前我不会问这种问题,
一旦我知道它们在哪里,我就不需要问,因为我可以很容易地找到,因为a)所有编译语言都会生成我可以查看的汇编语言或中间语言at,b) 我可以运行它 10^6 次,然后对其进行计时。
我的经验是,存在多种性能问题,其大小各不相同。首先我修复那些最简单/最大的。这使得其余部分花费更大的时间,以便在下一次遍历时更容易找到它们。**
我不断地进行调优,直到我解决不了性能问题。
到那时,代码可能比开始时要快得多。
** 示例:假设程序需要 10 秒。假设有两个问题(看了才知道),它们分别占 50% 和 30%。你修复了第一个,时间就减少到 5 秒。现在第二个问题消耗了60%,因为总时间减少了,所以更容易发现。修复此问题后,时间会缩短至 2 秒 - 速度提高 5 倍。问题越多,可能的加速就越显着。人们可能会怀疑它们是否存在如此大的问题,如果是这样,抽样将证明或反驳它。
I'm a performance freak too, and I've learned that
This kind of question is not something I even ask until I know where the performance problems are,
Once I do know where they are, I don't need to ask, because I can easily find out, because a) all compiled languages generate assembly or intermediate language that I can look at, and b) I can run it 10^6 times and just clock it.
My experience is there are multiple performance problems, having a range of sizes. First I fix the ones that are easiest / biggest. That makes the rest of them take a larger percent of the time so they are easier to find on the next pass.**
I keep doing tuning passes until I run out of performance problems I can fix.
By that time the code can be way faster than it was to begin with.
** Example: Suppose the program takes 10 seconds. Suppose there are two problems (you don't know till you look) and they take 50% and 30%, respectively. You fix the first one, and time drops to 5 seconds. Now the second problem is consuming 60%, because the total time has decreased, so it is much easier to spot. Fix it and time drops to 2 seconds - a 5x speedup. The more problems there are, the more dramatic the possible speedup. One may doubt that they have such large problems, and if so, sampling will prove or disprove it.
C++/CLI 编译为 MSIL 时没有性能优势,就像 C# 和 VB.NET 一样。您可以用 VB 和 C++/CLI 编写一些简单的测试函数来亲自查看。
There's no performance advantage as C++/CLI compiles to MSIL, just like C# and VB.NET. You can write some simple test functions in both VB and C++/CLI to see for yourself.
顺便说一句,要将句柄存储在内存的非托管部分中,我只需要使用 GCHandle 结构 或 gcroot。
By the way, to store handles in unmanaged portions of memory, I just needed to use the GCHandle structure or gcroot.
使用 C++/CLI 可能获得的唯一性能提升是混合本机代码和托管代码。 C++/CLI 允许您为代码的性能关键部分调用本机方法,且开销比 VB.Net 更少。我不建议到处在本机和托管之间切换,因为仍然存在惩罚,但将控制权传递给本机代码以获取与性能相关的代码块是可以接受的。
The only performance gain you might see with C++/CLI is where you mix native and managed code. C++/CLI allows you to call native methods for performance critical sections of code with less of an overhead than VB.Net. I wouldn't recommend switching between native and managed all over the place, as there is still a penalty, but passing control to native code for a chunk of performance related code is acceptable.
虽然 C++/CLI 编译器可能无法为代码的直接转换提供更好的性能,但许多 C++ 功能即使在托管代码中也可以提供巨大的性能优势。
其中一大因素是模板。针对模板参数的每个组合重新生成并独立优化代码。虽然 .NET 泛型通常会抑制最琐碎的内联,但转换为 C++/CLI 模板可以提供额外的优化机会,以及任何其他 .NET 语言中没有的等效项的专业化和编译时元程序。
While the C++/CLI compiler may not give better performance for a direct translation of the code, there are a number of C++ features which can give huge performance benefits even in managed code.
A big one is templates. The code is regenerated and independently optimized for each combination of template parameters. While .NET generics often inhibit even the most trivial inlining, conversion to C++/CLI templates enable additional optimization opportunities, as well as specialization and compile-time metaprograms which have no equivalent in any other .NET language.
性能增益来自于将非托管代码与托管程序集混合。 C++/cli 使这变得非常容易。尝试通过 c# 或 vb.net 使用 pinvoke 调用 c++ ...您要么必须将 c++ 包装在 extern c 调用中,要么通过其损坏的名称来调用 c++。此外,您还可以从优化的 Microsoft C++ 编译器中获得相当不错的性能提升。如果您不混合非托管代码,则不会有任何性能提升,因为它会像其他人提到的那样全部编译为 MSIL。
The performance gain comes from mixing unmanaged code with your managed assembly. C++/cli makes this very easy. Try calling c++ with pinvoke through c# or vb.net ... you'll either have to wrap the c++ in extern c calls or call the c++ by it's mangled name. Also you are getting the performance gain from optimized Microsoft C++ compilers which is fairly good. If you don't mix unmanaged code then there is no performance gain as it all compiles to MSIL like others have mentioned.