两个进程中的多线程通过共享内存进行通信会导致速度大幅下降,然后核心映射会恢复它

标签 multithreading ipc multicore shared-memory

我有一个 java 进程和一个 C++ 进程通过共享内存段相互通信(使用 jni 进行 java 端通信)。如果 Java 中有 1 个线程,C++ 中有 1 个线程,则代码运行速度不错,但是一旦我在进程中使用多个线程,性能就会下降很多(几乎 100 倍)。

在此之后我调整了代码中的一些东西(我在我的 core2duo 系统上运行)并发现当我将 java 进程映射到一个核心上时说 core0 和 core1 上的 cpp 进程(使用 sched_affinity() ) 性能恢复。

为什么会这样?我认为问题可能是对共享内存段的缓存争用,但后来,这个核心映射提高了性能。此外,仅当使用多个线程时才会观察到该行为。如果两个进程都使用单线程,速度是正常的。

最佳答案

当您有两个线程全速运行时,“最佳”配置是每个线程都有一个核心。如果它们不四处移动,即每个线程都停留在“它的”核心上,那么与它们在核心之间来回移动相比,您将获得更好的性能。因此,本质上,2+2 线程解决方案将需要 4 个核心才能以最佳方式运行。

此外,由于两个核心运行相同的代码,因此(在您的情况下)不要将它们从“它们的”核心中移出是至关重要的。这是因为两个内核的操作环境或多或少是相同的,这使得它们之间的切换(在缓存级别)比需要将所有内容加载到不同内核时更不麻烦。

然后你有内存系统饱和的问题。一个“正常”的单线程程序通常会用完大部分(如果不是全部的话)可用内存带宽。它的速度通常取决于内存系统向它提供数据的速率。有一些异常(exception)情况,例如当您处于除法指令中时没有内存事件发生,或者当您处于不需要数据读取或写入的紧密循环中时。在大多数其他情况下,内存系统会竭尽全力将内存插入程序,而且很多时候并没有程序使用内存的速度快。

不考虑这一点的程序在多线程上的运行速度会比单线程慢,因为两个线程在需要内存访问时会开始冲突,这会大大降低速度。这适用于已编译的语言,例如 C 或 C++。对于 Java,有很多内存访问在后台进行(由引擎引起),程序员几乎无法控制这些访问。因此,Java 引擎及其工作将耗尽大量缓存内存和带宽,这意味着您的共享内存将与引擎的需求竞争,并或多或少不断地进出缓存。

我的两分钱。

关于两个进程中的多线程通过共享内存进行通信会导致速度大幅下降,然后核心映射会恢复它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10862911/

相关文章:

.net - 如何实现分布式信号量?

android - Android中两个进程如何共享相同的代码?

c++ - 使用逻辑线程运行程序

multithreading - 如何在一个处理器内核上执行多个线程

objective-c - 如何使用 Objective C 在 OSX 上实现分布式对象?

cpu - XMM 寄存器总数或每个内核

ios - observeValueForKeyPath 总是从主线程调用吗?

android - 广播接收器中的线程未发生网络调用

c - 消息队列。消息发送 : Invalid argument

java - 使用 SwingWorker 可运行对象从 ExecutorService 获取正确类型的 Future