为什么OpenMP没有加速这段代码?

时间:2015-10-12 11:59:03

标签: c++ openmp

为了练习OpenMP,我决定编写一个算法来减少矩阵行。令人惊讶的是,当我添加和#pragma omp并行到我的内循环时,尽管我的程序花了99%的时间在内循环中,但没有明显的速度增加。我不期望在我的四核i7上看到4倍的性能提升,但我确实希望看到一些东西。

void Matrix::row_reduce(dim_t eff_width)
{   
    if(eff_width == 0 || eff_width > w)
        eff_width = w;

    dim_t* leads = new dim_t[h];

    double t1 = omp_get_wtime();

    for(dim_t r1 = 0; r1 < h; r1++)
    {
        dim_t lead = 0;
        double* ptr1 = (*this)[r1];
        while(lead < eff_width && ptr1[lead] == 0)
            ++lead;

        leads[r1] = lead;

        if(lead == eff_width)
            continue;
        //makeing this for parallel has no effect in speed
        #pragma omp parallel for
        for(dim_t r2 = 0; r2 < h; r2++)
        {
            if(r2 == r1)
                continue;

            if((*this)[r2][lead] == 0)
                continue;

            double scale = -(*this)[r2][lead] / ptr1[lead];
            add_scaled_row(r2, r1, scale);
            (*this)[r2][lead] = 0;
        }
    }
    t1 = omp_get_wtime() - t1;

    double t2 = omp_get_wtime();
    for(dim_t r = 0; r < h; r++)
    {
        if(leads[r] < eff_width)
            scale_row(r, 1.0 / (*this)[r][leads[r]]);
    }
    t2 = omp_get_wtime() - t2;

    double t3 = omp_get_wtime();
    for(dim_t i = 0; i < h; i++)
    {
        dim_t min = i;
        for(dim_t j = i + 1; j < h; j++)
        {
            if(leads[min] > leads[j])
                min = j;
        }
        if(min != i)
        {
            dim_t tmp = leads[i];
            leads[i] = leads[min];
            leads[min] = tmp;
            swap_rows(min, i);
            printf("SWAP\n");
        }
    }
    t3 =  omp_get_wtime() - t3;

    double total = t1 + t2 + t3;
    printf("t1 = %lf\t%lf\n", t1, 100 * t1 / total);
    printf("t2 = %lf\t%lf\n", t2, 100 * t2 / total);
    printf("t3 = %lf\t%lf\n", t3, 100 * t3 / total);

    delete[] leads;
}

这里的内环显然是平行的。可以从每行完全独立地消除主导项。我想也许没有性能提升,因为瓶颈是记忆,但我仍然期望稍微提升性能。

此外,如果有人对此感兴趣,那么我的add_scale_row函数。

void Matrix::add_scaled_row(dim_t dest_r, dim_t src_r, double f)
{
    if(dest_r == src_r)
    {
        scale_row(dest_r, 1.0 + f);
        return;
    }
    double* __restrict__ s = (*this)[src_r];
    double* __restrict__ d = (*this)[dest_r];

    __m256d vf = _mm256_set1_pd(f);

    for(dim_t i = 0; i < w; i += 4)
    {
        __m256d a = _mm256_load_pd(s + i);
        __m256d b = _mm256_load_pd(d + i);
        b = _mm256_fmadd_pd(a, vf, b);
        _mm256_store_pd(d + i, b);
    }
}

我还通过调用omp_get_num_threads检查了我的循环,它给出了我的8(4核X 2超线程)。我还检查了我的系统监视器,当我运行它时,它似乎显示所有核心都以100%运行。我在Ubuntu 15.04上使用GCC 4.9。

0 个答案:

没有答案