OpenMP For L oop замедляется за счет увеличения потоков - PullRequest
0 голосов
/ 10 марта 2020

У меня есть простой для l oop над массивом. Это становится медленным, когда я использую больше процессоров. Вот код:

#include <omp.h>
#include <sys/time.h>
#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

int main(int argc, char* argv[])
{
    string nth;
    if(argc<2)
    {
         cout << "Not enough parameters have been passed. \n";
         cin.get();
         exit(0);
    }
    else
    {
       nth=argv[1];
    }

    N=1000;
    vector<vector< int> > I;
    int *array= new int[N];
    // Initialize I and array

    struct timeval time_start;
    gettimeofday(&time_start, NULL);
    for (int y=0; y<I.size(); y++) {
        int i= I[y][0];
        int j= I[y][1];
        if (array[i]!=array[j]) {
            int a=array[i];
            int b=array[j];
            int min=min(a,b);

        #pragma omp parallel for shared (a,b,min)
            for (int n=0; n<N; n++)
            {
                if (array[n]==a || array[n]==b) {
                    array[n]=min;
                }
            }
        }
}

    struct timeval time_end;
    gettimeofday(&time_end, NULL);
    double sectiontime = (time_end.tv_sec * 1000000 + time_end.tv_usec) - (time_start.tv_sec * 1000000 + time_start.tv_usec);
    cout<<"Section Time: "<<sectiontime<<endl;
    delete array;
    I.clear();
    return 0;
}

Я компилирую это как:

g++ test.cpp -fopenmp -o outTestPar -std=c++0x

и запускаю по:

./outTestPar 2

Я запускаю его на машине с 64 сердечники. Я получаю это как результаты:

С 2 процессорами:

[...]$ ./outTestPar 2
Section Time: 28003
[...]$ ./outTestPar 2
Section Time: 20897
[...]$ ./outTestPar 2
Section Time: 19506
[...]$ ./outTestPar 2
Section Time: 22990

С 4 процессорами:

[...]$ ./outTestPar 4
Section Time: 20362
[...]$ ./outTestPar 4
Section Time: 19963
[...]$ ./outTestPar 4
Section Time: 28147
[...]$ ./outTestPar 4
Section Time: 20857

С 8 процессорами:

[...]$ ./outTestPar 8
Section Time: 24881
[...]$ ./outTestPar 8
Section Time: 28056

С 16 процессорами:

[...]$ ./outTestPar 16
Section Time: 24332
[...]$ ./outTestPar 16
Section Time: 26921

С 32 процессорами:

[...]$ ./outTestPar 32
Section Time: 21858
[...]$ ./outTestPar 32
Section Time: 23367
[...]$ ./outTestPar 32
Section Time: 25200
[...]$ ./outTestPar 32
Section Time: 24813

Как видите, не только нет улучшений, но иногда становится еще хуже. Есть идеи, что происходит? Как я могу улучшить это? Я также пробовал разные графики (stati c, Dynami c, руководствуясь). Не сработало и ухудшило положение.

1 Ответ

1 голос
/ 10 марта 2020

Параллелизация l oop очень мала и ограничена памятью. Для насыщения памяти не требуется слишком много ядер, и после этого производительность падает.

Вы также можете иметь проблемы с кэшем, если разные потоки записывают в одну и ту же строку кэша. Подробная информация об этом зависит от аппаратного обеспечения, но, как правило, если один поток записывает значение, вся строка кэша будет недействительной для других потоков, в результате чего они перезагружают строку, если они все еще ее используют.

В одну сторону уменьшить влияние записи в память означает, что запись производится только при изменении значения. Таким образом, вместо того, чтобы проверять «a» или «b», затем записывать минимум двух значений, попросите ваш оператор if проверить большее из двух значений и заменить его на меньшее значение. Это уменьшит количество записей в память, не записывая значения, которые не меняются.

...