我试图在每次迭代中改变线程数的同时对计算f(x)
进行基准测试。
f(x)=c*ln(x)*cos(x)
n=10000000
for (int pp = 2; pp<17; pp++)
{
p = pp;
int chunk = n/p; //acts like floor
omp_set_num_threads(p);
double start_parallel = omp_get_wtime();
//start parallel
#pragma omp parallel shared(tt,chunk) private (i)
{
//printf("thread number %d\n",omp_get_thread_num());
#pragma omp for schedule(dynamic,chunk) nowait
for(i=0; i<n; i++)
{
//tt[i] = f(tt[i]);
tt[i] = f1(tt[i]); //the speed up is much higher with f1 since log and cos
//computations are polynomial; see function.
}
} //end parallel
double end_parallel = omp_get_wtime();
double cpu_time_used_parallel = (double) (end_parallel - start_parallel);
printf("parallel: for n=%d, p=%d, time taken=%f, speedup=%f\n",
n,p,cpu_time_used_parallel,
cpu_time_used_seq/cpu_time_used_parallel);
}
结果:
已开始更改线程:
并行:对于n=10000000,p=2,所用时间=0.153774,加速=3.503831
并行:对于n=10000000,p=3,所用时间=0.064447,加速=8.360370
平行:n=10000000,p=4,所用时间=0.044694,加速=12.055239
平行:n=10000000,p=5,所用时间=0.048700,加速比=11.063550
平行:n=10000000,p=6,所用时间=0.039009,加速=13.811989
平行:n=10000000,p=7,所用时间=0.041735,加速=12.910017
平行:n=10000000,p=8,所用时间=0.041268,加速=13.055919
并行:对于n=10000000,p=9,所用时间=0.039032,加速=13.804157
并行:对于n=10000000,p=10,所用时间=0.038970,加速=13.825767
平行:n=10000000,p=11,所用时间=0.039843,加速=13.522884
并行:对于n=10000000,p=12,所用时间=0.041356,加速=13.028237
并行:对于n=10000000,p=13,所用时间=0.041039,加速比=13.128763
平行:n=10000000,p=14,所用时间=0.047433,加速比=11.359218
平行:n=10000000,p=15,所用时间=0.048430,加速比=11.125202
平行:n=10000000,p=16,所用时间=0.051950,加速=10.371477
注意:这里的加速比是根据顺序算法计算的(threads=1)
加速似乎并没有受到
p
(线程数)变化的真正影响。我这样做是对的,还是源于线程数量的非有效增加(即理论上说更改
p
不会严重影响O(myprogram)
)? 最佳答案
问:我这样做对吗。。。?A:不,对不起,你做得不对。让我们一起分析原因,并勾勒出一些HPC级绩效基准的提示:
好吧,你已经知道最初的基准设计不是精心设计的。附加成本的影响,在当代的criticism of the original, overhead-naive Amdahl-law has more details on this和时间细节中得到了很好的展示,因为实例化成本相对于其他处理类和I/O相关成本越来越小,如下所示。
为什么?
与“计算”部分相比,代码具有巨大的附加开销。这是其他合法语法构造器(OpenMP在这里,map reduce在其他地方,list comprehension在其他情况下,或其他一些语法提示技巧)的技术能力使用有缺陷的最有力标志
最终的表现是一种平衡的艺术(正确地平衡成本和收益——任何一种不平衡都意味着失去了表现优势)。
成本?在这里?看看结果的前景:
第二个罪过是忽略了“幕后”对域缩放的惩罚。[TIME]
越大,分配的内存就越大,缓存线的低效率(可怕的)带来的惩罚就越多,所有这些都是零保护,不会落入内存交换的地狱:
n=1E3 1E4 1E5 1E6 1E7 1E8 1E9 :
______________________________________________________________________________:_____
1.000 1.000 1.000 1.000 1.000 1.000 1.000 : p= 1
0.930 1.403 0.902 1.536 1.492 1.517 0.356 : p= 2
1.075 2.319 2.207 1.937 2.001 1.991 1.489++ : p= 3
1.497+++++ 2.636++++ 1.563 1.657 2.571 2.144 0.687 : p= 4
1.226++ 2.548+++ 0.957 2.025 2.357 1.731 1.569++++ : p= 5
1.255+++ 1.805 2.704 2.020 2.348 1.502 0.989 : p= 6
0.957 0.581 3.104++ 2.124 2.486 2.002 0.838 : p= 7
1.151 1.376 2.449 2.154 2.573 1.536 0.776 : p= 8
1.135 1.685 2.388 2.506+++ 2.852++++ 2.311 1.676+++++ : p= 9
1.285++++ 2.492++ 2.497 2.568++++ 2.647+ 2.467 1.413+ : p=10
1.177 2.314+ 2.709+ 2.174 2.688+++ 2.634++++ 0.606 : p=11
1.216+ 2.293 2.442 2.287 2.550 2.551++ 1.256 : p=12
1.034 2.148 1.802 2.361++ 2.635 2.554+++ 1.181 : p=13
0.999 0.440 3.672+++++ 2.774+++++ 2.927+++++ 2.839+++++ 1.496+++ : p=14
1.091 1.217 3.285++++ 2.284 2.525 2.356 1.005 : p=15
0.937 2.850+++++ 3.185+++ 2.334+ 2.655++ 2.508+ 0.889 : p=16
提高性能的技巧?
如果基准计算,基准计算并避免MEM-I/O
如果进行基准测试,请始终检查整个环境,以感受(更好地了解如何避免/消除任何此类扭曲测量结果的情况)缓存中的副作用
始终避免任何形式的共享(可以避免-将处理映射到缓存线相干块中的
[SPACE]
的不相交区域,但覆盖“整个”n
,以避免错误共享和“至少”重复使用已提取数据块中已支付MEM-I/O提取成本的任何数据(如果基于向量的加载/存储确实是必须看到的)允许并积极利用FMA4/SIMD/AVX512提供的任何HPC矢量化技巧