C# 到 C++ 多线程,有啥问题吗?

Posted

技术标签:

【中文标题】C# 到 C++ 多线程,有啥问题吗?【英文标题】:C# to C++ multithreading, any issues to expect?C# 到 C++ 多线程,有什么问题吗? 【发布时间】:2015-05-15 05:46:50 【问题描述】:

经过大量测试后,我有十几种算法在 C# 中没有给我令人满意的速度,但在 C++ 中工作得很好(实现方式相同,几乎从 C# 复制粘贴到 C++,大量基于大型数组数据集)。

现在我知道如何从 C# 调用 C++ 代码并且我不想切换整个应用程序,所以我正在考虑这样做。然而,这些微内核必须大量并行运行,并且由于 .net 中的并行性非常好,我正在考虑在这方面处理它,并让 C# 中的每个线程调用任何相关的内容。

听起来我不应该有任何线程安全问题(我没有调用任何 C++ lib 功能,所有方法都只是将数组作为输入并返回数组作为输出,数据不共享跨 C++ 或 C# 端的线程)。但是因为我从来没有这样做过,所以我的问题是:这完全愚蠢吗?我是不是在房间里错过了一头巨大的大象,还是我应该没事?我是否需要担心我是在 C++ 端使用 MT 运行时还是不考虑我不调用任何系统调用?

每个微内核都足够慢(100+ms),.net 边界交叉不是一个大问题,并且在 C++ 中速度更快,但我宁愿避免移植我的所有代码和测试以意识到我错过了一些明显的东西。

【问题讨论】:

现在还有单线程运行时吗? 没有任何线索,我在上次检查的选项中看到了不同的运行时,但我的问题不是专门针对这个的,我通常不使用 C++,并且想确保不需要为此做任何特别的事情以这种方式使用(以避免出现类似“哦,你不知道编组到 C++ 库不是线程安全的?”之类的意外情况,经过大量的测试工作,显然是假的例子,但因为我没有知识,我宁愿问也不愿浪费时间) 嗯,你确实提到了这个问题。但是,正如您所描述的,从不同的线程调用 pinvokes 应该没有问题。不过我想我会使用 C++/CLI。 不就是添加第三层吗?听起来像是更多的工作 作为一般规则,互操作可能更有效。为什么那会是第三层。将 C++ 代码编译成 C++/CLI 模块。 【参考方案1】:

不调用任何 C++ 库功能,所有方法都只是将数组作为输入并返回数组作为输出,数据不会在 C++ 或 C# 端的线程之间共享

由于线程之间没有数据共享,我认为你是安全的。

【讨论】:

是的,它完全是无共享的,每个线程在 C# 端都有自己的一组数组,不接触其他线程的数据,因此将并行调用也没有共享的 C++ 库状态,因此可能有数百个线程将调用同一个库,但每个线程都传递自己的数据,并取回它们的专用数组,而任何一方都没有共享任何内容【参考方案2】:

是的,这样做是安全的,但跨 C++/C# 分界的编组会产生一些开销。

一些想法:

考虑使用 C++ CLI

如果您的算法是数据并行的,请考虑通过托管库使用 GPU 或通过 C++ 使用 CUDA(有托管包装器)

我还没有在 .net 中使用过 RyuJIT(新的 jit 编译器),但它也能够使用 SIMD 指令,而无需使用 C++。

【讨论】:

我的算法不支持 SIMD(我不能按顺序获取数组的 4 或 8 个元素并对每个元素应用相同的过程),由于大小,GPGPU 也是不可能的我正在使用的数据集(目标硬件是 160 线程/2TB 服务器)。在我的测试中,只要我不以顺序方式读取,C++ 编译器就会为我提供更好的数组读/写结果,因此是切换的原因(某些算法以 4 倍的速度运行)。 我已经瞄准了.net 4.6,因此使用ryujit,性能仍然太慢:( 在这样的数据量下,很可能 GC 过于激进。 C++ 可能确实是要走的路(正如您在原始问题中描述的那样) GC 似乎并不是真正的问题,即使在以单线程方式(几十 MB)进行小型测试时也会发生这种情况,它的性能也非常稳定(与 GC 峰值不一致) ) 和免费分配(数组被重用)。它只是在顺序访问上比 C++ 慢一些,但在非顺序访问上要慢得多(即使针对数组中的邻居也是如此)。不知道为什么真的 你能分享更多信息吗?我有点好奇...你也可以给我发个 pm (malionet at gmail)

以上是关于C# 到 C++ 多线程,有啥问题吗?的主要内容,如果未能解决你的问题,请参考以下文章

c++ 多线程与c多线程有啥区别?

多线程:线程多于内核有啥意义?

C# 多线程 ,可以多个线程做一任务,并且提高做任务的效率吗

asp.net(C#) 是 多线程吗

Java的多线程有啥用处

C++ 多线程 同时读取同一个vector 线程安全 吗