Fast C++ program, C# GUI, possible?
我正在开发一个应用程序,它将以每秒大约2000行(帧)的速度处理来自行扫描照相机的数据。对于这种实时应用,我觉得C/C++是前进的道路。(这是我的感觉,其他人会同意托管代码不适合此任务。)
但是,我已经做了很少的MFC,或者任何其他的C++ GUI。不过,我真的要把C guis做好了。
所以在C/C++中编写数据密集型代码和C语言中的GUI是很自然的。图形用户界面将用于设置/校准/在线监测(并可能通过UDP输出数据,因为它在C中更容易实现)。
所以首先,我想看看是否有人同意这样做。根据我的编程经验(擅长低级C算法和高级C图形用户界面设计),感觉很好。
其次,我不确定该怎么做。我刚刚在VS2005中构建了一个解决方案,它从C应用程序调用了一些(extern"c")dll函数。为了确保我能做到这一点,我在dll中写入了一些全局变量,并从中读取:
测试h
1 2 3 | int globaldata; extern"C" __declspec(dllexport) void set(int); extern"C" __declspec(dllexport) int get(); |
测试程序
1 2 3 4 5 6 7 8 | extern int data=0; __declspec(dllexport) void set(int num) { data = num; } __declspec(dllexport) int get() { return data; } |
试验室
1 2 3 4 5 | [DllImport("test")] private static extern void set(int num); [DllImport("test")] private static extern int get(); |
调用
现在,我知道您也可以导出C++类,但是必须管理它吗?这是怎么回事?我走这条路对吗?
谢谢你的帮助!
首先,感谢您迄今为止的精彩回答!我对堆栈溢出总是印象深刻…
我想我应该多了解一点,不一定是原始速度(这可以是原型和基准)。我更关心的一件事是垃圾收集器的非确定性行为。此应用程序在执行垃圾收集时不能容忍500ms的延迟。
我完全赞成在纯C中进行编码和尝试,但是如果我提前知道GC和任何其他不确定的.NET行为(?)会导致一个问题,我想我的时间会更好地花在C/C++上编码,并找出最好的C接口。
没有理由不能完全用C语言编写高性能代码。
性能(C编程指南)
Rico Mariani的性能博客(一个优秀的资源)
调整.NET应用程序性能
关于相同/相似主题的问题:
- C++与Java/C语言的性能
- C++比C语言快多少?
其他条款:
- 微基准C++、C语言和Java
- 利用C的特性为科学计算项目提供动力
- 使用Visual Studio探查器查找应用程序瓶颈
- C语言对C++性能的影响
我认为你的解决方案是合理的:
你的解决方案,如果你还没有解决它,被称为"混合模式",这基本上意味着你在相同的项目中组合托管的(C)和非托管的(C/C++)代码,这常常是一个麻烦,让VS项目运行起来(LNK2020错误…AGH..),但是当你找到正确的设置时,它应该工作得很好。
唯一的缺点是,混合模式程序集必须完全信任地运行,如果可以的话,我想您知道该怎么做。
另一件你可能想看的事情是一个名为swig的开源项目。SWIG接受你的C/C++代码,并从中创建.NET程序集,我在我的TM+++开源项目中使用过它。有关swig的更多信息,请参阅此处http://www.swig.org/。
对于实时应用程序:我建议C++,您将更灵活地使用内存管理,更快,甚至多平台取决于使用什么框架……
关于框架和GUI,我建议您看一下Qt。Qt是C++软件开发的一个很好的框架。
我想这是解决你问题的办法!
你需要做的第一件事就是测试你的假设。您的性能约束是什么?您希望承载应用程序的硬件类型是什么?用C语言编写一个处理核心问题的小程序,并测量它的运行速度。
只有当你有了事实,你才能决定是否使用C/C++来管理解决方案。
与其他评论过的人一样,我怀疑C/托管解决方案会很好地解决问题,特别是如果您使用.NET并行扩展。
如果你最终进入C/C++路径,那么有两个选项RealIopp,即pNoCKE和COM互操作。我不相信有一种干净的方式直接从.NET访问非托管C++类;为此,您将不得不考虑实现托管/非托管C++程序集。
我的公司做了一些非常相似的事情,虽然用的是CCD相机而不是线扫描相机。我们使用的是用于低层算法的GUI、网络通信、高级"管道"和C++/CLI。它工作得很好。您将永远无法在Windows上编写真正的实时系统,保证最大响应时间,但根据我的经验,GC是您在这里遇到的最少的问题。一方面,GC只在分配内存时运行;C/C++中的MALOC/NEW也是如此,它们也需要时间(想想内存碎片)。根据我们所做的测量,完整的GC需要10-50毫秒,并且在这段时间内不需要停止其他线程(我认为除非它们尝试分配托管内存),这对我们来说是可以的。但我不确定这些数字是否可以推广到任何类型的应用程序,您可能应该做您自己的分析来确定。
如果您担心您的GUI可能会破坏您的实时约束,那么您可以考虑将实际的图像处理放到单独的进程中,并使用管道/套接字与GUI通信。或者至少在设计系统时要记住这个选项,所以如果您真的遇到了不可预见的性能问题,您可以将它作为最坏的选择。
你的第二个问题是,对于实际的算法,你应该使用C++还是C语言。就我个人而言,在编写复杂的图像处理算法时,我觉得C++更舒服。我认为语言更适合这个任务,C/C++的数字压缩库比C语言多。但这可能是个人偏好的问题。从性能的角度来看,C++的优点是C++内联优于.Net JIT内联(即它可以内嵌更多的小函数调用)。
如果您选择使用C++,我建议使用C++/CLI:这样,您就可以编写编译成托管代码的C++类。C++优化器将优化它们,只有到本地代码的最后编译步骤将由.NET JIT完成。最大的优点是您可以直接从C++/CLI访问.NET类,并且可以很容易地在C ++/CLI中创建托管类,这些类可以从C ^中访问。您不需要在围栏的两侧编写包装器代码。(C++/CLI有点笨拙,因为它包含了用于托管和非托管编程的语言构造,但是如果您已经熟悉了非托管C++和C语言,那么您可能不会有任何理解它的问题)。
对于C++,你使用C++ + CLI——实际上并不是那么糟糕。它比旧的托管扩展要好得多。
对表现发表评论。这要看情况而定。你的C++代码和C代码之间有多少来回?是否有后台线程在C++中收集数据,并周期性地将其发送到C代码?如果你要连接一个设备,它会使用串行接口,USB,一些你已经得到的API吗?
我同意米奇的100%。
如果在调查了他的资源之后,你仍然觉得你需要使用一些非托管代码,你可以在C++中写一个"业务"层(或者在这种情况下,真的是一个功能层),并将你的UI写在C语言中。使用COM interop从C/托管代码调用非托管代码。
不过,我还是觉得你不需要这么做。
前端WPF和C++后端(PNEKEK)很快,但是当你在线程上做GUI工作时,你的GUI线程不会被你的后台代码阻塞。当你这样做的时候,你的程序看起来会更快、更轻。
我有一个在本地C/C++和C非常低延迟系统的经验。
在C/C++中,80%的处理器时间在确定性的Maloc方法中丢失,但是本机代码比MSIL代码快10X。
在C中,内存分配更快,因为它是一个异步进程
您的选择必须通过以下比率完成:处理时间/malloc编号
那么粒度!!!!
C/C++的解决方案是内存中的预AcLARS缓冲区(如果需要的话,使用预取L2/L3缓存)
C的解决方案是最小化P-invoke转换机制
恭喜你的计划,保罗
我已经用C++.NET完成了。
由于C++.NET和C语言都被管理,所以我不明白为什么不能这么做。关键是你会怎么做。
我的扫描仪有高达3000行/秒,但关键的策略是一次显示32行的数据块。我没有严格的实时要求,所以有时我可能会有点落后。如果实时对您非常重要,您应该考虑切换平台。
有一个叫做"InTime OS"的实时Windows解决方案,但是使用起来很痛苦。
另一种方法是将硬实时划分为单独的DLL或库,并让C以自己的速度显示它可以做什么。实际上,用户永远无法判断你的界面是2000帧还是500帧。
您将选择的语言不会对性能产生太大影响(假设您可以影响速度5/10%)。有什么区别的是你将使用的算法,你如何处理数据,分析你的应用程序,等等…(性能可能以10倍的比率变化)。
为什么是Windows?它的内存性能和网络性能都比任何一个unix都差。对测线传感器的专门捕获意味着您需要一个设备来处理原始输入。首先考虑使用正确的操作系统,这将大大降低您必须处理的其他压力(我非常熟悉线扫描仪技术)。