C++ openMp优化动态阵列访问

C++ openMp优化动态阵列访问,c++,multithreading,optimization,openmp,C++,Multithreading,Optimization,Openmp,我试图用一个或四个线程来测量并行部分的加速比。由于我的平行部分相对简单,我预计速度会提高近四倍。以下是我的问题: 由于我的并行部分在四个内核上的运行速度是只有一个内核的两倍,我相信我仍然没有找到性能损失的原因 我想尽可能地将我的函数iter并行化。该函数使用动态数组的条目和专用数量来更改其他动态数组的条目。因为每个迭代步骤只使用相应循环步骤的数组项,所以我没有不同的线程访问同一数组项。此外,我还考虑了由于访问同一缓存线中的条目而导致的错误共享。我的猜测是,这是一个次要的影响,因为我的双数组长度为

我试图用一个或四个线程来测量并行部分的加速比。由于我的平行部分相对简单,我预计速度会提高近四倍。以下是我的问题: 由于我的并行部分在四个内核上的运行速度是只有一个内核的两倍,我相信我仍然没有找到性能损失的原因

我想尽可能地将我的函数iter并行化。该函数使用动态数组的条目和专用数量来更改其他动态数组的条目。因为每个迭代步骤只使用相应循环步骤的数组项,所以我没有不同的线程访问同一数组项。此外,我还考虑了由于访问同一缓存线中的条目而导致的错误共享。我的猜测是,这是一个次要的影响,因为我的双数组长度为5*10^5,并且通过为scheduledynamic chunk命令选择一个合理的块大小,我不希望不同的线程同时访问给定缓存线中的极少数entires。在我的模拟中,我有大约80个这样的阵列,因此在堆栈上分配它们并不舒服,而且为每个线程制作私有副本也不成问题。 有人有想法吗,如何改进?在开始编译器优化之前,我想完全理解这为什么如此缓慢

同样让我吃惊的是:使用parallel=false调用iterparallel比使用parallel=true和omp\u set\u num\u threads1调用要慢

main.cpp:

int main(){

    mathClass m;
    m.fillArrays();

    double timeCount = 0.0;
    for(int j = 0; j<1000; j++){
        timeCount += m.iter(true);
    }

    printf("meam time difference = %fms\n",timeCount);
    return 0;
}
mathClass.cpp:

mathClass::mathClass(){
    length = 5000000;

    A = new double[length];
    B = new double[length];
    C = new double[length];
    D = new double[length];
}

void mathClass::fillArrays(){
    int temp;

    for ( int i=0; i<length; i++){
        temp = rand() % 100;
        A[i] = double(temp);

        temp = rand() % 100;
        B[i] = double(temp);

        temp = rand() % 100;
        C[i] = double(temp);
    }   
}

double mathClass::iter(bool parallel){
    double startTime;
    double endTime;
    omp_set_num_threads(4);
    startTime = omp_get_wtime();

    #pragma omp parallel if(parallel)
    {
        int alpha;                  // private in all threads

        #pragma omp for schedule(static)
        for (int i=0; i<length; i++){
            alpha = 15*A[i];    
            D[i] = C[i]*alpha + B[i]*alpha*alpha;   
        }

    }
    endTime = omp_get_wtime();
    return endTime - startTime;
}

循环体中的计算是内存限制的-它对读取或写入的每个字节的数据执行的触发器太少。因此,一旦内存带宽完全饱和(即使只有一个线程也可能出现这种情况),添加新线程不会导致进一步的加速。这听起来像是一个严重的问题。有没有一种简单的方法来检测饱和带宽?我在虚拟机中运行这个程序应该不会有什么不同,对吧?你可以用LIKWID之类的东西监视CPU的硬件计数器。它能够测量内存带宽利用率。
mathClass::mathClass(){
    length = 5000000;

    A = new double[length];
    B = new double[length];
    C = new double[length];
    D = new double[length];
}

void mathClass::fillArrays(){
    int temp;

    for ( int i=0; i<length; i++){
        temp = rand() % 100;
        A[i] = double(temp);

        temp = rand() % 100;
        B[i] = double(temp);

        temp = rand() % 100;
        C[i] = double(temp);
    }   
}

double mathClass::iter(bool parallel){
    double startTime;
    double endTime;
    omp_set_num_threads(4);
    startTime = omp_get_wtime();

    #pragma omp parallel if(parallel)
    {
        int alpha;                  // private in all threads

        #pragma omp for schedule(static)
        for (int i=0; i<length; i++){
            alpha = 15*A[i];    
            D[i] = C[i]*alpha + B[i]*alpha*alpha;   
        }

    }
    endTime = omp_get_wtime();
    return endTime - startTime;
}