Распараллеливание функции с помощью openMP на C

Я написал программу, которая вводит размер матрицы и количество потоков, а затем генерирует случайную двоичную матрицу из нулей и единиц. Затем мне нужно найти кластеры из единиц и присвоить каждому кластеру уникальный номер.

Я получаю вывод правильно, но у меня проблема с распараллеливанием функции.

Мой профессор попросил меня разбить строки матрицы на части «thread_cnt». то есть: размер потока равен 4, а размер матрицы равен 8, тогда он разбивается на 4 матрицы, каждая из которых имеет 2 строки.

Код выглядит следующим образом:

//Inputted Matrix size n and generated a binary matrix rand1[][]
//
begin = omp_get_wtime();
width = n/thread_cnt;
#pragma omp parallel num_threads(thread_cnt) for
for(d=0;d<n;d=d++)
{
    b=d+width;
    Mat(d,b);
    d=(d-1)+width;    
}

Mat(int w,int x)
{
//printf("\n Entered function\n");
for(i=w;i<x;i++)
{    
    for(j=0;j<n;j++)
    {
        //printf("\n Entered the loop also\n");
        //printf("i = %d, j = %d\n",i,j);
        if(rand1[i][j]==1)
        {
            rand1[i][j]=q;
            adj(i,j,q);
            q++;
        }
    }
}
}

adj(int p, int e, int m)            //Function to find adjacent 1's 
{   
//printf("\n Entered adj function\n");
//printf("\n p = %d e = %d m = %d\n",p,e,m);
if (rand1[p][e+1] == 1)
{
    //printf("Test1\n");
    rand1[p][e+1]=m;
    adj(p,e+1,m);
}
if (rand1[p+1][e] == 1)
{
    rand1[p+1][e]=m;        
    //printf("Test2\n");
    adj(p+1,e,m);
}
if (rand1[p][e-1] == 1 && e-1>=0)
{
    rand1[p][e-1]=m;
    //printf("Test3\n");
    adj(p,e-1,m);

}
if (p-1>=0 && rand1[p-1][e] == 1)
{
    rand1[p-1][e]=m;
    //printf("Test4\n");
    adj(p-1,e,m);
}

}

Код дает мне правильный результат. Но время увеличивается, а не уменьшается, когда я увеличиваю количество потоков. Для 1 потока я получаю 0,000076, а для 2 потоков - 0,000136.

Похоже, это итерация вместо распараллеливания. Может ли кто-нибудь помочь мне в этом?

PS: Мне нужно показать как последовательное время, так и параллельное время и показать, что у меня есть увеличение производительности из-за распараллеливания.


person user2014179    schedule 26.01.2013    source источник
comment
ваша петля выглядит странно. а почему вы устанавливаете произвольное количество потоков? openmp предназначен для создания оптимального количества потоков для вас.   -  person Andreas Grapentin    schedule 27.01.2013
comment
Как мне это сделать? Извините, я хорошо разбираюсь в C, но я новичок в openMP   -  person user2014179    schedule 27.01.2013
comment
вы просто используете #pragma omp parallel for, и openmp волшебным образом решит все остальное (кроме синхронизации)   -  person Andreas Grapentin    schedule 27.01.2013
comment
и вам, вероятно, следует использовать более крупный пример для определения времени. меньшие примеры, как правило, имеют странное поведение по времени из-за постоянных накладных расходов на создание потока   -  person Andreas Grapentin    schedule 27.01.2013
comment
Если я использую только #pragma omp parallel, как тогда моя матрица разбивается на части? Как мне переписать свой код?   -  person user2014179    schedule 27.01.2013
comment
Что ж, тебе следует самому разбить матрицу на части. Обычно pragma omp parellel for работает таким образом, что выполняет итерации цикла параллельно. Итак, вам нужно определить последовательный цикл, который разбивает работу, которую необходимо выполнить, на отдельные части, а затем позволить механизму параллельных вычислений проработать детали.   -  person Andreas Grapentin    schedule 27.01.2013
comment
Я не знаю, сколько потоков сгенерирует omp. Так что я не могу сам сломать матрицу, не зная, сколько потоков будет сгенерировано. Это так сбивает с толку.   -  person user2014179    schedule 27.01.2013
comment
затем сначала попробуйте версию pthreads, чтобы понять, как работает параллельное кодирование, затем попробуйте openmp. это не так уж и сложно, как только вы поняли общую идею :)   -  person Andreas Grapentin    schedule 27.01.2013
comment
Ваш рекурсивный алгоритм не останавливается на границе между двумя подблоками, принадлежащими разным потокам. Почему бы вместо этого не реализовать алгоритм Хошена-Копельмана?   -  person Hristo Iliev    schedule 27.01.2013


Ответы (1)


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

 tid = omp_get_thread_num();

Затем вы должны сделать простое сопоставление: если pid - это я, работаю с (i + 1) -й подматрицей, где 0 ‹= i‹ = nthreads-1, что, возможно, может быть закодировано как:

Mat(i*width,i*width+width)
person woryzower    schedule 26.01.2013
comment
это не правильно. каждый поток будет вычислять итерацию цикла. - person Andreas Grapentin; 27.01.2013