接上去,我们来看一下多核下的功用成绩,参看如下的代码。两个线程在操作一个数组的两个不同的元素(无需加锁),线程循环 1000 万次,做加法操作。在下面的代码中,我高亮了一行,就是p2指针,要么是p[1],或是 p[18],实际下去说,无论拜访哪两个数组元素,都应该是一样的执行时间。
void fn (int* data) {
for(int i = 0; i < 10*1024*1024; ++i)
*data += rand ();
}
int p[32];
int *p1 = &p[0];
int *p2 = &p[1]; // int *p2 = &p[30];
thread t1(fn, p1);
thread t2(fn, p2);
但是,并不是,在我的机器上执行上去的结果是:
关于 p[0] 和 p[1] :560ms
关于 p[0] 和 p[30]:104ms
这是由于 p[0] 和 p[1] 在同一条 Cache Line 上,而 p[0] 和 p[30] 则不能够在同一条 Cache Line 上 ,CPU 的缓冲最小的更新单位是 Cache Line,所以,这招致虽然两个线程在写不同的数据,但是由于这两个数据在同一条 Cache Line 上,就会招致缓存需求不断进在两个 CPU 的 L1/L2 中停止同步,从而招致了 5 倍的时间差异。
示例五
接上去,我们再来看一下另外一段代码:我们想统计一下一个数组中的奇数个数,但是这个数组太大了,我们希望可以用多线程来完成,这个统计。下面的代码中,我们为每一个线程传入一个 id ,然后经过这个 id 来完成对应数组段的统计义务。这样可以加快整个处置速度。
int total_size = 16 * 1024 * 1024; //数组长度
int* test_data = new test_data[total_size]; //数组
int nthread = 6; //线程数(由于我的机器是 6 核的)
int result[nthread]; //搜集结果的数组
void thread_func (int id) {
result[id] = 0;
int chunk_size = total_size / nthread + 1;
int start = id * chunk_size;
int end = min (start + chunk_size, total_size);
for ( int i = start; i < end; ++i ) {
if (test_data[i] % 2 != 0 ) ++result[id];
}
}
(责任编辑:admin)