c++ - 为什么 4 个进程比 4 个线程好?

标签 c++ multithreading operating-system intel

void task1(void* arg) {
    static volatile long res = 1;
    for (long i = 0; i < 100000000; ++i) {
        res ^= (i + 1) * 3 >> 2;
    }
}

4 个线程,同时工作,在 30 秒内执行 task1 193 次。但是 4 个进程,同时工作,在 30 秒内执行 task1 348 次。为什么会有这么大的差异? 我在 [Mac OS X 10.7.5,Intel Core i5(4 个逻辑内核)] 上对其进行了测试。想一想,Windows 和 Linux 中的相同差异。

最佳答案

res 变量是static,这意味着它由同一进程中的所有线程共享。这意味着在有四个线程的情况下,一个线程中 res 变量的每次修改都必须可供其他线程使用,这通常涉及总线上的某种锁定、 1 级缓存并在所有其他 CPU 中重新加载。

在四个进程的情况下,变量并没有真正被不同的进程共享,所以它们可以真正地并行运行,互不干扰。

请注意,主要区别不在于线程/进程,而在于在一种情况下每个人都访问同一个变量,而在另一种情况下他们访问不同的变量。此外,对于线程,真正的问题不是性能,而是最终结果可能不正确的事实:

res ^= x;

那不是原子操作,处理器会加载res的旧值,然后在寄存器中修改它并写回。如果没有同步原语,多个线程可以加载相同的值,独立修改它并写回变量,在这种情况下,一些线程的工作将被其他线程覆盖。最终结果将取决于不同线程的执行模式,而不是您的程序代码。

要模拟变量的非共享,您需要确保在线程中访问不同的缓存行。最简单的更改是从变量中删除 static 限定符,这样每个线程都会更新它自己的堆栈中的变量,该变量与其他线程的变量位于不同的内存地址中,并且希望映射到不同的缓存行。另一种选择是一起创建四个变量,但在它们之间添加足够的填充,以便它们分布到不同的缓存行:

struct padded_long {
    volatile unsigned long res;
    char [CACHE_LINE_SIZE - sizeof(long)]; // Find this in your processor documentation
};
void f(void *) {
   static padded_long res[4];
   // detect which thread is running based on the argument and use res[0]..res[3]
   // for the different threads

关于c++ - 为什么 4 个进程比 4 个线程好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16635535/

相关文章:

c++ - 是否可以从大括号类型的初始化中推断出元组的模板参数?

c++ - 通过 Winsock 在 C++ 中发送/接收结构

C# 下载器 : should I use Threads, BackgroundWorker 还是 ThreadPool?

java - 如何使用java 8集合并行流处理设置负载平衡?

operating-system - 虚拟内存空间

c - 为什么我可以在声明前使用结构类型的指针

c++ - 说一个C++对象是可 move 的,这到底意味着什么?

c++ - boost memory_order_consume 示例

python - 'gi.repository.Gtk' 对象没有属性 'gdk'

linux - 如何在 linux 中读取正在运行的进程的线程组 ID