在多核的CPU架构中,每一个核心core都会有自己的缓存空间,因此如果一个变量如果同时存在不同的核心缓存空间时,就会出现伪共享(false sharing)的问题。
此时如果一个核心修改了该变量,该修改需要同步到其它核心的缓存。
在linux执行cat /proc/cpuinfo 来查看cpu的缓存的行大小:
cache_alignment : 64,
在目前的Intel处理器中cache是64B对齐的,因此K * 64与(K + 1) * 64 - 1的内存块在同一cache行中。
查看下面一段代码
01.#include
02.#include
03.#include
04.#include
05.#include
06.#include
07.using namespace std;
08.
09.
10.
11.#define NMAX 4096 * 10
12.#define NUM_CORE 4
13.
14.int g_iBuff[NMAX];
15.
16.
17.int main()
18.{
19. int alignPos = 0;
20. for (int i = 0; i < 65; ++i)
21. {
22. if (((int)&g_iBuff[i]) % 64 == 0)
23. {
24. alignPos = i;
25. break;
26. }
27. }
28.
29. for (int pos = 1; pos <= 4096; pos <<= 1)
30. {
31. memset(g_iBuff, 0 , sizeof(g_iBuff));
32. time_t beg = time(0);
33.#pragma omp parallel for num_threads(NUM_CORE)
34. for (int i = 0; i < NUM_CORE; ++i)
35. {
36. int tp = i * pos + alignPos;
37. for (int j = 0; j < 999999999; ++j)
38. {
39. g_iBuff[tp]++;
40. }
41. }
42. time_t end = time(0);
43.
44. cout << "false shareing: step = "<<pos<<" time = "<< end - beg << "s" <<endl;
45. }
46.
47. return 0;
48.}
# g++ XX.cpp -o xx -fopenmp
# ./xx
我们首先来看一下这段代码的输出结果:
false shareing: step = 1 time = 12s
false shareing: step = 2 time = 13s
false shareing: step = 4 time = 13s
false shareing: step = 8 time = 6s
false shareing: step = 16 time = 3s
false shareing: step = 32 time = 3s
false shareing: step = 64 time = 3s
false shareing: step = 128 time = 3s
false shareing: step = 256 time = 3s
false shareing: step = 512 time = 3s
false shareing: step = 1024 time = 3s
false shareing: step = 2048 time = 3s
false shareing: step = 4096 time = 3s
接下来我们来分析一个程序:
01.for (int i = 0; i 16, 也不会再存在伪共享。
这样我们就可以解释上程序在不同step上的执行时间问题。
原文地址:
http://g.csdn.net/5216086