为什么在多线程中使用 memcpy 性能会下降?

Why memcpy performance deteriorates when used in multible threads?

我在 Linux 上写了一个简短的测试程序来测试 memcpy 在多线程中使用时的性能。我没想到它会如此毁灭性。执行时间从 3.8 秒增加到 2 分钟多,而 运行 程序的两个实例同时花费了大约 4.7 秒。这是为什么?

// thread example
#include <iostream>       
 #include <thread>         
#include <string.h>
using namespace std;

void foo(/*int a[3],int b[3]*/)
{
  int a[3]={7,8,3};
  int b[3]={9,8,2};

  for(int i=0;i<100000000;i++){
    memcpy(a,b,12*(rand()&1));
    }
}


int main()
{

#ifdef THREAD

  thread threads[4];
  for (char t=0; t<4; ++t) {
    threads[t] = thread( foo );
  }

  for (auto& th : threads) th.join();            
  cout << "foo and bar completed.\n";

#else

  foo();
  foo();
  foo();
  foo();

#endif

  return 0;
}

您的 memcpy 不执行任何操作,因为 12 * rand() & 1 始终是 0,因为它被读取为 (12 * rand()) & 1。由于 12 是偶数,结果总是 0.

所以您只是在测量 rand() 的时间,但该函数使用一个共享的全局状态,该状态可能(或可能不)由所有线程共享。看起来在您的实现中它是共享的并且它的访问是同步的,因此您的竞争很激烈并且性能受到影响。

尝试使用 rand_r(),它不使用共享状态(或新的和改进的 C++ 随机生成器):

  unsigned int r = 0;
  for(int i=0;i<100000000;i++){
       rand_r(&r)
    }

在我的机器上,这将多线程运行时间从 30 秒减少到 0.7 秒(单线程为 2.2 秒)。 当然,这个实验没有说明 memcpy(),但它说明了共享全局状态...