What factors should I consider when choosing between C# and C++ for an image-processing project?
I want to develop some image processing code and I am wondering if there is a big difference between developing them in C++ and C#?
Is there any detail document that explains what is good to implement in C# and what is good to implement in C++?
As far as I know, since C# code are compiled to machine code just before running (using .NET CLR JIT compiler), there should not be a lot of difference between the two language if during code development, you look how the specific language suggest to implement a design patterns (For example, using a lot of new versus of using a fixed arrays).
Edit: There are some other parameters that I did not think at first but I am looking at the now when I read some of the answers: 1- It is a high level projects which means that I can ask the user to have a very good computer (A lot of memory and multi-core processors) 2- I can assume that user has a very good gra开发者_开发技巧phic card, so I may be able to use its GPU for processing. 3- I think WPF is good for this development (Am I right!). Is there any similar library for C++? I worked with MFC, but I am not sure that MFC is as good as WPF when working on projects that needs to show images and the GUI is very important.
.NET IL is compiled to machine code, just as C++. But almost always the C++ code will be faster, because:
- The compilation time becomes part of the runtime (once only, but sometimes this is an issue)
- JIT-compilers spend less time on optimization than AOT-compilers, for the reason mentioned above. Therefore the code generated by a JIT is generally slower. For instance, JITs usually do not vectorize anything, which is important for image-processing. Most often, it isn't even possible to generate vectorized code due to VM restrictions (Mono.Simd is an exception)
- Languages in a VM have to ensure that the program does not escape the VM. For instance, they have to check array bounds on every access (unless the compiler can prove that the index is always in range; keep in mind that JIT compilers do not spend much time on such analyses).
- For time-critical kernels you can insert assembler-instructions by yourself. VMs don't allow this because the assembler may break out of the VM.
In some cases managed code can be faster than unmanaged code:
- A garbarge collector allows memory to be allocated more efficiently than malloc. But, unless the memory just used for a short time, however Mark-And-Sweep also needs some time.
- A JIT may compile code with more static assumptions on the code (like, it knows all possible implementations of a virtual function) and redo the compilations when the assumption does not hold anymore. This is done in Java HotSpot, but not in Microsoft's JIT nor Mono.
Summary: If execution speed is important, use C++. But C# can be fast enough, as Paint.NET shows. Also consider the option to code mostly in C# and once you are not satisfied with the speed of some important function, reimplement it in C++/CIL or call your optimized function using P/Invoke.
As someone who has converted an image processing library from C++ to C#, and done the benchmarks the language has little influence on the speed of what you are doing, more important are the algorithms you are using and which api's you are using to manipulate the images (i.e. in windows use lockbits on the bitmap). I managed to gain significant speed increases due to the fact that is possible for me to write more parallel code a lot easier in C# than in C++ and the ability to not be stuck with just Monitor.Wait (I'll admit I am not a C++ threading expert, in fact I am not a C++ threading amateur) but having a wide variety of options to easily parallelize operations (which in graphics are pretty intrinsic) made for massive speed increases when converting from C++ to C# (plus only having to worry about freeing up resources and not memory made life a lot easier too). Obviously if you are very comfortable in C++, then you can write faster code in C++, but you know C++ and SIMD quite well to beat C# compiler. I should also note that we converted from C++ to C# assuming that we would lose about 10% speed, and the reason we converted was the cost in time of adding new features was so high that a rewrite to C# became worth our while, the end product ending up being faster was just a bonus (now also I should mention that the original library was written before SIMD extension where added to Visual C++, so using it was no available to the original library author).
While you're correct that .NET code gets JIT-compiled to machine code, you have to realize that you have very little control over that process. You don't get to choose the target instruction set, and while the managed code advocates claim JIT compilation is superior because it can use the fastest instruction set available on a per-machine basis, the fact is that this hasn't been implemented yet.
Bottom line: You can write C++ code using SSE instructions that will be run 4 times faster than JIT-generated code on the same CPU.
Some other things worth mentioning: SIMD parallelism is a lot easier to write, and a lot easier for the compiler to optimize, than multithreading. There is no overhead with SIMD, but thread synchronization isn't free. And there are fewer hidden gotchas with SIMD, so it's much easier to get linear speedup. It's SO easy for multiple threads to fall into cache line sharing and contention. And managed languages give you absolutely no control over false sharing.
Yes, C# makes it easier to do multithreading. Poorly. C++ makes it much more feasible to do multithreading right, and you may get enough speed out of tuning single-threaded code that you don't even need to deal with the extra complexity of threads.
If you're determined to optimize yourself, here are some techniques: (stop at any point along the line once you've reached the desired performance, since the more you apply the more complex your code will be)
Work on the raw data, don't use some API that adds indirection and abstraction over a bunch of pixels. Not only can this slow you down, it interferes with the next bunch of improvements. (Kris alluded to
LockBits
vsSetPixel
, the native routine for raw image access isGetDIBits
)Cache tuning. A simple approach is to unroll your innermost loop by a factor of 16 or so. Then invert the loop nesting order. This will result in processing rectangular chunks of the data, which generally are interdependent, so you access each piece of data many times for each cache fill. It's a waste to use a cache profiler at this stage, though.
Use SIMD. Process 4 or more times as many pixels in each loop iteration. Easy win. Especially since you've already unrolled the loop somewhat, those identical instructions are just sitting there begging to be combined. But it can't be done until you break free of the abstractions.
Now use a cache profiler. SIMD fetches have significantly different characteristics than scalar instructions, so you should do this after the SIMD conversion.
Maybe multithreading. If the problem's really big. Pay careful attention to cache line sizes. And try to never write to data that other threads also use. Definitely don't write the same data from multiple threads.
It's depend on how good are you on both language, if you are really an expert in image processing programming or algorithm, c++ will give you more freedom for your acrobatic in optimizations. But if you are not that expert, safe yourself by using higher level language
There are a few factors to consider...
Are there any libraries that you might want to use - if there are and they are .Net then that may influence your decision in favour of C#.
However, I think it is safe to say that most intensive numerical applications (and image processing is basically numerically intensive operations on a 2D matrix) would be written in native code. There is one very good exception to this - take a look at Paint.Net, it is almost entirely written in managed code and is has excellent perfromance and functionality (http://getpaint.net).
What is the purpose of your application? If it is a "hobby" or learning excercise then go with whatever language you feel happiest with. If it's a commercial application I'd look at the library options first.
精彩评论