多线程 – 与每个物理核心绑定的线程并行的memset
我一直在
In an OpenMP parallel code,would there be any benefit for memset to be run in parallel?测试代码,我正在观察一些意想不到的事情.
我的系统是一个单插槽Xeon E5-1620,它是一个Ivy Bridge处理器,有4个物理内核和8个超线程.我使用的是Ubuntu 14.04 LTS,Linux Kernel 3.13,GCC 4.9.0和EGLIBC 2.19.我用gcc -fopenmp -O3 mem.c编译 当我在链接中运行代码时,它默认为八个线程并给出 Touch: 11830.448 MB/s Rewrite: 18133.428 MB/s 但是,当我绑定线程并将线程数设置为这样的物理核心数 export OMP_NUM_THREADS=4 export OMP_PROC_BIND=true 我明白了 Touch: 22167.854 MB/s Rewrite: 18291.134 MB/s 触控率增加了一倍!绑定后运行几次总是比重写更快.我不明白这一点.绑定线程并将其设置为物理核心数后,为什么触摸比重写更快?为什么触控率翻倍? 这是我使用的代码,没有修改Hristo Iliev的答案. #include <stdio.h> #include <string.h> #include <omp.h> void zero(char *buf,size_t size) { size_t my_start,my_size; if (omp_in_parallel()) { int id = omp_get_thread_num(); int num = omp_get_num_threads(); my_start = (id*size)/num; my_size = ((id+1)*size)/num - my_start; } else { my_start = 0; my_size = size; } memset(buf + my_start,my_size); } int main (void) { char *buf; size_t size = 1L << 31; // 2 GiB double tmr; buf = malloc(size); // Touch tmr = -omp_get_wtime(); #pragma omp parallel { zero(buf,size); } tmr += omp_get_wtime(); printf("Touch: %.3f MB/sn",size/(1.e+6*tmr)); // Rewrite tmr = -omp_get_wtime(); #pragma omp parallel { zero(buf,size); } tmr += omp_get_wtime(); printf("Rewrite: %.3f MB/sn",size/(1.e+6*tmr)); free(buf); return 0; } 编辑: Touch: 14723.115 MB/s,Rewrite: 16382.292 MB/s Touch: 14433.322 MB/s,Rewrite: 16475.091 MB/s Touch: 14354.741 MB/s,Rewrite: 16451.255 MB/s Touch: 21681.973 MB/s,Rewrite: 18212.101 MB/s Touch: 21004.233 MB/s,Rewrite: 17819.072 MB/s Touch: 20889.179 MB/s,Rewrite: 18111.317 MB/s Touch: 14528.656 MB/s,Rewrite: 16495.861 MB/s Touch: 20958.696 MB/s,Rewrite: 18153.072 MB/s 编辑: 我在其他两个系统上测试了这个代码,我无法重现它们的问题 i5-4250U(Haswell) – 2个物理内核,4个超线程 4 threads unbound Touch: 5959.721 MB/s,Rewrite: 9524.160 MB/s 2 threads bound to each physical core Touch: 7263.175 MB/s,Rewrite: 9246.911 MB/s 四个插座E7- 4850 – 10个物理内核,每个插槽20个超线程 80 threads unbound Touch: 10177.932 MB/s,Rewrite: 25883.520 MB/s 40 threads bound Touch: 10254.678 MB/s,Rewrite: 30665.935 MB/s 这表明将线程绑定到物理内核确实改善了触摸和重写,但触摸比在这两个系统上重写要慢. 我还测试了memset的三种不同变体:my_memset,my_memset_stream和A_memset. my_memset结果: Touch: 22463.186 MB/s Rewrite: 18797.297 MB/s 我认为这表明问题不在EGLIBC的memset函数中. A_memset结果: Touch: 18235.732 MB/s Rewrite: 44848.717 MB/s my_memset_stream: Touch: 18678.841 MB/s Rewrite: 44627.270 MB/s 看一下asmlib的源代码,我看到了用于编写非时间存储的大块内存.这就是my_memset_stream获得与Agner Fog的asmlib相同的带宽的原因. maximum throughput of this system is 51.2 GB/s.所以这表明A_memset和my_memset_stream获得了大约85%的最大吞吐量. void my_memset(int *s,int c,size_t n) { int i; for(i=0; i<n/4; i++) { s[i] = c; } } void my_memset_stream(int *s,size_t n) { int i; __m128i v = _mm_set1_epi32(c); for(i=0; i<n/4; i+=4) { _mm_stream_si128((__m128i*)&s[i],v); } } 解决方法
从您的数字可以看出,您的4个绑定线程在2个物理内核上运行,而不是预期的4个物理内核.你能证实一下吗?它可以解释Touch时间加倍.我不确定在系统上使用超线程时如何强制线程到物理核心. {我尝试将其添加为一个问题,但没有足够的“声誉”}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |