Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++CLI. Are native parts written in pure C++ but compiled in CLI as fast as pure native C++?

Tags:

c++

c++-cli

I want to delegate audio computing to a C++ layer, but handle and edit audio content through a WPF GUI.

I have had a brief look at C++/CLI, and I wanted to know:

  • should I use C++/CLI as an intermediate layer between C# GUI and C++ audio management
  • or should I simply put my code in C++/CLI and expect it to be compiled the same way, thus as efficient.

EDIT: as the flaming war may begin. This is a link that goes to the benchmarks game, that clearly states the C/C++ as a speed winners. I am asking: Should I write my C++ in a C++ Dll, or in a C++CLI assembly.

like image 915
Stephane Rolland Avatar asked Apr 17 '11 12:04

Stephane Rolland


3 Answers

In C++/CLI, managed types (ref class for example) and their members are compiled to MSIL. This means no use of SIMD, and much less optimization (at least in the current version of .NET, and the reasons given by Microsoft aren't changing any time soon, although they could change their assessment of the tradeoffs).

Native types, on the other hand, can be compiled either to MSIL or to native machine code. Although Visual C++ doesn't have the best C++ optimizer in the world, it's very very good. So my recommendation would be to compile to native code. Visual C++ will use C++ interop when calling in between managed and native code, which is very efficient (it's the same internalcall technology used for all .NET's built-in functions such as string concatenation).

To make this happen, you can either put your time-critical code in a separate object file (not separate DLL!, let the linker combine managed and unmanaged code together into a "mixed-mode" assembly) compiled without /clr, or bracket it with #pragma managed(push, off) ... #pragma managed(pop). Either way will get you maximum optimizations and allow you to use SIMD intrinsics for very speedy code.

like image 175
Ben Voigt Avatar answered Nov 18 '22 18:11

Ben Voigt


Bridging the C++/CLI layer is a marshalling effort, where managed state is converted to primitive types to marshal to the unmanaged layer, processed, and then marshalled back. Depending on your algorithm, (and pragmatics for "wrapping" that transition layer), it is best to keep the marshalling as bounded (small) as possible.

So, it depends on the problem: The simplest problem would be an interface that sends a little primitive data across the C++/CLI layer, process a LONG time, and then send a little data back (e.g., minimal marshalling overhead). If your algorithm requires more extensive interaction across the C++/CLI layer, it gets quite a lot more tricky.

The benefit of "All C#" or "All Managed" is (1) skipping this marshalling layer (which is overhead, and sometimes tedious depending on the work), and (2) run-time optimizations that the .NET engine can make for the specific computer on which the code is running (which you can't have with native C/C++, nor unmanaged code).

I agree with other comments in this thread that you should/must "test" it with your scenarios. A "big" C++/CLI layer with performance-sensitive transition is very hard to do, because of the "boxing/unboxing" that (automatically) occurs when you keep jumping between managed/unmanaged.

Finally, the ultimate performance difference between the hybrid "managed/unmanaged" design versus the "all-managed" design relates to the trade-offs between: Can the .NET engine make machine-specific optimizations of the .NET code (for example, taking advantages of machine-specific threads/cores/registers), greater than the "pure native" code (which is linked into the mixed-mode assembly) is able to process FAST by bypassing the .NET engine (which is an interpreter)?

True, well-written native code can "detect" processor threads, but typically cannot detect machine-specific registers (unless compiled for that target platform). In contrast, native code does not have the "overhead" of going through the .NET runtime, which is merely a virtual machine (that may be "accelerated" through Just-In-Time compiling of some logic to its specific underlying hardware).

Complicated problem. Sorry. IMHO, there are just no easy answers on this type of problem, if "performance sensitive" is your issue.

like image 43
charley Avatar answered Nov 18 '22 19:11

charley


I recommend you take a look at this article. Also, when trying to decide what's best for your code to be written in, you should (always) do a small test for your case, to see if there are any differences for the exact case you have there.

like image 2
Andrei Pana Avatar answered Nov 18 '22 19:11

Andrei Pana