27

I'm looking into developing an application that will process data from a line-scan camera at around 2000 lines (frames) per second. For this real-time application, I feel that C/C++ are the way to go. (It is my feeling, and others will agree that Managed code just isn't right for this task.)

However, I've done very little MFC, or any other C++ GUI. I am really getting to do C# GUIs very well, though.

So it seems natural to me to write the data-intensive code in C/C++, and the GUI in C#. The GUI will be used for set-up/calibration/on-line monitoring (and possibly outputting of data via UDP, because it's easier in C#.

So first, I'd like to see if anyone agrees that this would be the way to go. Based on my programming experience (good at low-level C algorithms, and high-level C# GUI design), it just feels right.

Secondly, I'm not sure the right way to go about it. I just threw together a solution in VS2005, which calls some (extern "C") DLL functions from a C# app. And to make sure I could do it, I wrote to some global variables in the DLL, and read from them:

test.h

int globaldata;
extern "C" __declspec(dllexport) void set(int);
extern "C" __declspec(dllexport) int  get();

test.cpp

extern int data=0;
__declspec(dllexport) void set(int num) {
    data = num;
}

__declspec(dllexport) int get() {
    return data;
}

test.cs

[DllImport("test")]
private static extern void set(int num);

[DllImport("test")]
private static extern int get();

Calling get() and set() work properly (get() returns the number that I passed to set()).

Now, I know that you can export a C++ class as well, but does it have to be managed? How does that work? Am I going about this the right way?

Thanks for all your help!

*** EDIT ***

First of all, THANK YOU for your fantastic answers so far! I'm always incredibly impressed with Stack Overflow...

I guess one thing I should have hit on more, was not necessarily raw speed (this can be prototyped and benchmarked). One thing that has me more concerned is the non-deterministic behavior of the Garbage Collector. This application would not be tolerant of a 500ms delay while performing garbage collection.

I am all for coding and trying this in pure C#, but if I know ahead of time that the GC and any other non-deterministic .NET behavior (?) will cause a problem, I think my time would be better spent coding it in C/C++ and figuring out the best C# interface.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • This sounds like a seriously cool project – Robert Venables Aug 08 '09 at 16:07
  • 1
    To help reduce your concerns about garbage collection" Generation 2 collections (the expensive type), will not normally happen until memory comes under pressure. If your application is a good .NET citizen (i.e. always calls dispose on IDisposable objects, and does NOT manually call GC.Colect()) then you should not experience large delays. – Mitch Wheat Aug 09 '09 at 02:09
  • 1
    @Mitch. Not in my experience, I've seen G2 collections occur very often on a non-memory constrained system that was not often idle. Check the perfmon counter to see for yourself, GC happens far more than you think it does. Its still quite quick on modern hardware, but that may not be good enough for the OP. – gbjbaanb Oct 09 '09 at 12:46

12 Answers12

32

There is no reason that you can't write high performance code entirely in C#.

SO questions on the same/similiar topic:

Other articles:

Community
  • 1
  • 1
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
  • 3
    That's one of C# biggest advantages over Java...**pointers**. – Kredns Aug 08 '09 at 04:42
  • 5
    As far as I am aware .NET *still* doesn't support SIMD instructions. Mono does but that's little different story. So yes on some tasks C++ esspecially compiled with ICC will be significally faster. – Ray Aug 08 '09 at 05:38
  • 1
    @Ray: strictly speaking the question wasn't about whether .NET doesn't support SIMD instructions.... – Mitch Wheat Aug 08 '09 at 06:59
  • 1
    It actually was Mitch: "... I'm looking into developing an application that will process data from a line-scan camera at around 2000 lines (frames) per second." – Ray Aug 08 '09 at 08:25
  • @Ray: so use multiple threads. – Mitch Wheat Aug 08 '09 at 09:37
  • 8
    Thread usage will not compensate lack of SIMD support. – Ray Aug 08 '09 at 13:00
  • 1
    True on both counts. .NET code is not necessarily slower than naive code, as Mitch's links show. In many cases, managed code turns out faster than native, even. ( http://blogs.msdn.com/ricom/archive/2005/05/10/performance-quiz-6-chinese-english-dictionary-reader.aspx is a particularly enlightening read), but true, if you're able to take advantage of SIMD, native code gains a significant advantage. But in the general case, it is a bad idea to assume that "I need performance, so I'd probably better write in C/C++". Those languages do not magically make your code go faster. – jalf Aug 08 '09 at 13:17
  • 1
    .Net CLR uses SIMD instructions for some internal operations (memory operations, some math operations etc.) so you do get some SIMD with .Net, but currently it doesn't use SIMD when compiling CIL to native code. – Pop Catalin Aug 09 '09 at 03:27
  • From a practical perspective this is nonsense and has always been nonsense. The ways to write fast C++ code are well understood while the ways to write fast C# are not nearly as well understood. – Mikhail Dec 29 '12 at 22:45
  • @Mikhail: That is incorrect. – Mitch Wheat Dec 30 '12 at 00:05
17

In my opinion your solution is a sound one:

  1. Even though C# is fast it never can compete with a well written unmanaged C/C++, I have made high-performance applications myself that proves this beyond the tiny examples that people always post when someone posts these kinds of statements
  2. MFC or ATL UI programming is cumbersome and slow, C# is the way to go here, I NEVER will do MFC/ATL UI programming ever again, unless forced to

Your solution, in case you haven't figured it out yet, is called "Mixed Mode", which basically means that you combine Managed (C#) and Unmanaged (C/C++) code in the same projects, it is often a bit of a hassle to get the VS project up-and-running (LNK2020 errors..argh..) but when you find the right settings it should work just fine.

Only negative thing is that mixed mode assemblies must run in Full Trust, if that's OK then I guess you know what to do.

One other thing you might want to look at is an open source project called SWIG. SWIG takes your C/C++ code and creates a .NET assembly out of it, I have used it myself in my TM++ open source project. See here for more information about SWIG http://www.swig.org/.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • I've seen a few people mention SWIG before... one thing I'm concerned with is the development process... I'm planning on kind of writing both the GUI and the main app at the same time (the GUI allowing me to see what's going on in the main app). With SWIG, it seems that I could continually have to re-SWIG it before I could do anything with it from the C# GUI. Is this the case? I would think VS should be able to handle something like this with ease, no? – Jonathon Reinhart Aug 08 '09 at 17:10
  • Usually you dont have to change the SWIG interface definition file, you only need to add your C/C++ header-files to it, and in some cases you must do advanced stuff, but in most cases SWIG will scan your headers. Here is an example of a SWIG interface definiton file: http://tmplusplus.svn.sourceforge.net/viewvc/tmplusplus/trunk/src/TMPlusPlus.i?revision=350 –  Aug 08 '09 at 19:25
  • ..and to make your .NET assembly you can do something like this: swig -c++ -csharp -outdir ./SWIG -lcpointer.i TMPlusPlus.i where TMPlusPlus.i is the SWIG interface definition file above. –  Aug 08 '09 at 19:28
  • For the "Mixed Mode" method, I'm assuming I have one VS2005 Solution, with two projects in it, one being the C# GUI. What is the other? Is it C++ CLR? And once I write my (unmanaged) C++ class, can I still instantiate it in the C# and start a new thread on it? Or would I call a static function in the C++ from the C#, which would in tern instantiate itself... – Jonathon Reinhart Aug 08 '09 at 20:26
  • 3
    Hi, Jonathon. Yes, exactly, your solution has two clr projects (C++ and C#), and one unmanaged C/C++ project. From the Managed C++ project you can add your other C/C++ libraries (*.lib) as Additional Dependencies under Project Property Settings->Configuration Properties->Linker->Input in VS 2005. Your managed C++ project would work as a interface or wrapper for you unmanaged C/C++ project, how you call it is up to you. On another note, I should mention that it is also possible to call a C/C++ library (*.lib or COM DLL) directly from a C# project using DllImport, it's really up to you. –  Aug 09 '09 at 17:49
6

For real time application: I recommend C++, you will be more flexible with memory management, faster, and even multi-platform depending on what framework is used...!

About framework and GUI, I recommend you having a look at Qt. Qt is a great framework for C++ software development.

I guess it's the solution to your problem !

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matthieu
  • 2,743
  • 19
  • 21
5

The first thing you need to do is test your assumption. What are your performance constraints? What sort of hardware are you expecting to host the application? Write a small program in C# that deals with the core problem and measure how fast it runs.

Only once you have the facts can you make a decision about whether or not to use C/C++ over a managed solution.

Along with others who have commented, I suspect that a C#/managed solution will do just fine, especially if you make use of the .NET Parallel Extensions.

If you end up going the C/C++ route, then there are two options re interop, namely, pInvoke and COM interop. I don't believe there's a clean way to access unmanaged C++ classes directly from .NET; to this end, you would have to consider implementing a managed/unmanaged C++ assembly.

Eric Smith
  • 5,262
  • 2
  • 33
  • 49
5

My company does something very similar, although with CCD cameras instead of line-scan cameras. We're using C# for the GUI, network communication, high-level "plumbing" and C++/CLI for the low-level algorithms. It works quite well. You'll never be able to write a true realtime system with guaranteed maximum response times on windows, but from my experience the GC will be the least of your problems here. For one thing, the GC only runs when you allocate memory; so does malloc/new in C/C++, and they need time, too (think memory fragmentation). From the measurements we've done, a full GC takes 10-50ms and will not neccessarily stop the other threads during that time (unless they try to allocate managed memory, I think), which is ok for us. But I'm not sure if these numbers can be generalized to any kind of application, you probably should do your own profiling to be sure.

If you're afraid that your GUI might break your realtime constraints, you might consider putting the actual image processing into a separate process and communicate with the GUI using pipes/sockets. Or at least keep that option in mind when you design your system, so you have it as a worst-case option, if you really run into unforseen performance problems.

Your second question was if you should use C++ or C# for the actual algorithms. Personally, I feel more comforatble in C++ when I write complex image processing algorithms. I think the language is better suited for the task, and there are far more numbercrunching libraries for C/C++ than for C#. But that might be a matter of personal preference. From a performance point of view, C++ has the advantage that the C++ inliner is better than the .NET JIT inliner (i.e. it can inline more of your small function calls).

If you choose to use C++, I'd suggest using C++/CLI: That way, you can write C++ classes that are compiled into managed code. The C++ optimizer will optimize them, only the last compilation step to native code will be done by the .NET JIT. The big advantage is that you can directly access your .NET classes from C++/CLI, and you can easily create managed classes in C++/CLI that can be accessed from C#. You don't need to write wrapper code on both sides of the fence. (C++/CLI is a bit clunky because it contains language constructs for managed and for unmanaged programming, but if you're already familiar with unmanaged C++ and C#, you probably won't have any problems understanding it.)

Niki
  • 15,662
  • 5
  • 48
  • 74
  • 1
    "and you can easily create managed classes in C++/CLI that can be accessed from C#" so, I've done this, but what if I want unmanaged code for the data-processing part? In my C++/CLI code, I'm guessing I'd write the unmanaged class to do everything, and then a C++/CLI interface that the C# calls, and can access my "pure" C++? Still just kinda confused here... – Jonathon Reinhart Aug 08 '09 at 21:29
  • That really depends on your problem. Writing unmanaged classes + managed wrappers in C++/CLI is one way. Writing small unmanaged helper functions and calling those from a larger managed class is also possible. The C++/CLI compiler can emit IL and native code, it can compile "normal" C++ and it has special keywords to create managed classes. The managed classes may call into the unmanaged code/create unmanaged classes and vice versa. How you use that is really up to you. – Niki Aug 08 '09 at 22:28
2

For C++ you use C++/CLI - which is actually not that bad. It's a lot better than the old managed extensions.

To comment on performance. It really depends. How much back and forth will the there be between your C++ code and your C# code? Will you have a background thread gathering data in C++ and periodically sending that to the C# code? If you are going to be interfacing with a device, will it be using serial, USB, some API you have been given?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sylvanaar
  • 8,096
  • 37
  • 59
  • Yes, you've got it. The background thread will be gathering data from the frame buffer on the camera, and re-assembling the image, and making calculations. Then periodically the C# will poll (or the C++ will callback?) to provide some data, and the C# app will send this out via UDP socket. The interface depends on the hardware we select, but the one I've been looking at was USB 2.0, and they provided the C++ API. Is C++/CLI managed? Again, I'm worried about the non-deterministic GC causing sporadic delays as I manipulate a large amount of data. – Jonathon Reinhart Aug 08 '09 at 17:17
  • Performance also depends on other factors - for example, the C++/CLI implementation of STL is dreadfully slow, so much so the .NET containers outperform it. – gbjbaanb Oct 09 '09 at 12:29
1

I agree with Mitch 100%.

If after investigating his resources, you still feel that you need to use some unmanaged code, you can write a "business" layer in C++ (or in this case, really a functional layer) and write your UI in C#. Use COM Interop to call from C#/managed code to your unmanaged code.

Again, though, my feeling is that you will not need to do this.

Eric J.
  • 147,927
  • 63
  • 340
  • 553
0

The language you'll choose will not affect much the performance (say you can affect speed by 5/10%). What will make the difference is the algorithms you will be using, how you process data, profiling your application, etc... (performance could change with a ratio of 10x).

Nicolas Viennot
  • 3,921
  • 1
  • 21
  • 22
0

I've done it with C++.NET

Since both C++.NET and C# are managed I don't see why it could not be done. The point is how you will do it.

My scanner had up to 3000 lines / sec but the key strategy was to display blocks of 32 lines at a time. I didn't have hard real time requirements so I could be a little behind sometimes. If real time is very important to you, you should consider switching platform.

There is a real time windows solution called "InTime OS" but its really painful to use.

Another approach you can have is to separate the hard real time into a separate dll or library and have the C# show what it can at it's own speed. Really, the user will never be able to tell if your interface has 2000 fps or 500 fps

Eric
  • 19,525
  • 19
  • 84
  • 147
0

I have an experience in native C/C++ and C# very low latency systems.

  • in C/C++ 80 % of processor time is lost in deterministic malloc methods, but native code is 10x faster than msil code

  • in C# memory allocation is faster because it is a asynchrone process

Your choice must be done by the ratio : process time / malloc number

So Granularity !!!

The solution for C/C++ is pre-alloc alls buffers in memory (use prefetch L2/L3 cache if necessary)

The solution for C# is minimize P-Invoke conversion mechanism

Congratulations for your project, Paul

Paul
  • 19
  • 1
0

Front end wpf and c++ backend (pinvoke) is fast but when you do your GUI work on threads as well, your GUI thread doesn't get blocked by your background code. When you do that your program will look faster and light weight.

amarnath
  • 785
  • 3
  • 19
  • 23
Rahul
  • 11
  • 1
-2

Why windows? It has horrible memory performance and worse network compared with any of the unixes out there. Specialized capture of a line sensor implies you need an appliance to handle the raw input. Consider using the right OS first which will greatly lower the other pressures you'll have to deal with (I'm am very very familiar with line scanner technologies).

Brian
  • 81
  • 1
  • 5
  • 1
    Perhaps he doesn't want to try talking his customers into running something else than Windows? – erikkallen Aug 09 '09 at 21:32
  • +1: Worrying about GC latency while you're still running Windows is silly. – J D Sep 05 '11 at 22:25
  • Horrible memory performance? Take a look at this question : [Memory Cache .Net 4.0 performance](http://stackoverflow.com/questions/11729023/memory-cache-net-4-0-performance-test-astonishing-result) – lsalamon Sep 02 '12 at 15:06