C OpenMP在矩阵矢量产品上的工作很慢

C++ OpenMP working really slow on matrix-vector product

本文关键字:工作 OpenMP      更新时间:2023-10-16

所以,我正在使用OpenMP制作矩阵向量产品,但是我注意到它的工作原理很慢。经过一段时间,试图弄清楚了什么问题,我只是在并行部分中删除了所有代码,但它仍然很慢。这里有什么问题?(n = 1000)

这是1、2和4核的时间结果。

seq_method时间= 0.001047194215062

parralleal_method(1)时间= 0.001050273191140 seq -par = -0.000003078976079 seq/par = 0.997068404578433

parrallel_method(2)时间= 0.001961992426004 seq -par = -0.000914798210943 seq/par = 0.533740192460558

parralleal_method(4)时间= 0.004444448095121916 seq -par = -0.003400900906854 seq/par = 0.235425319459132

即使我从并行部分删除代码 - 它不会更改太大。

void parallel_method(float A[n][n], float B[n], float C[n], int thr_num)
{
    double t1, t2;
    float tmp = 0;
    int i, j;
    t1 = omp_get_wtime();

    omp_set_dynamic(0);
    omp_set_num_threads(thr_num);
#pragma omp parallel for private(tmp, j, i)
    for (i = 0; i < n; i++) {
        tmp = 0;
        for (j = 0; j < n; j++) {
            tmp += A[i][j] * B[j];
        }
#pragma omp atomic
        C[i] += tmp;
    }
    //////
    t2 = omp_get_wtime();
    if (show_c) print_vector(C);
    par = t2 - t1;
    printf("nparrallel_method (%d) time = %.15f", thr_num, par);
    printf("nseq - par = %.15f", seq - par);
    printf("nseq/par = %.15fn", seq / par);
}

代码:https://pastebin.com/q20t5dlk

我试图重现您的问题,但无法做到这一点。我的行为完全连贯。

n=100
sequential_method (0) time = 0.000023339001928
parallel_method (1) time = 0.000023508997401
parallel_method (2) time = 0.000013864002540
parallel_method (4) time = 0.000008979986887
n=1000
sequential_method (0) time = 0.001439775005565
parallel_method (1) time = 0.001437967992388
parallel_method (2) time = 0.000701391996699
parallel_method (4) time = 0.000372130998080
n=10000
sequential_method (0) time = 0.140988592000213
parallel_method (1) time = 0.133375317003811
parallel_method (2) time = 0.077803490007180
parallel_method (4) time = 0.044142695999355

除了小尺寸(螺纹上空头顶很重要),结果或多或少是预期的。

我做了什么:

  • 所有度量均在同一运行中完成

  • 我一次运行所有功能,而无需时间安排caches

在实际代码估计中,我也将

  • 时间连续执行相同的功能,尤其是在时间短以减少小变化

  • 的情况下
  • 运行多个实验,并保留最小的实验以抑制异常值。(我更喜欢最低限度,但您也可以计算平均值)。

您应该已经发布了所有代码,我不知道您的方法是什么。但是我认为您的估计在不同的运行中完成,而不会加热缓存。对于此代码,缓存影响非常重要,并且核心必须存储相同的信息(b)。而且问题不足以从较大的L1/L2缓存中受益。这些倍数负载可能解释了并行代码的较差性能。

在您的代码上的最后一句话中。每个线程都会有自己的i值。因此,C [i]只能通过一个线程访问,而原子化的实质是没有用的。