3

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

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

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

4

1 回答 1

3

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

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

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

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

我的两分钱。

于 2012-06-06T09:34:58.567 回答