我试图在每次迭代中改变线程数的同时对计算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相关成本越来越小,如下所示。
c - OpenMP基准测试并行计算-LMLPHP
为什么?
与“计算”部分相比,代码具有巨大的附加开销。这是其他合法语法构造器(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矢量化技巧

10-07 18:51