Проблема с синхронизацией программы, которая использует 1-8 потоков на сервере, который имеет 4 двухъядерных процессора? - PullRequest
1 голос
/ 25 июля 2010

Я запускаю программу на сервере в моем университете, который имеет 4 двухъядерных процессора AMD Opteron (tm) 2210 HE и O.S. это версия Linux 2.6.27.25-78.2.56.fc9.x86_64. Моя программа реализует Conways Game of Life и работает с использованием pthreads и openmp. Я рассчитал параллельную часть программы, используя функцию getimeofday (), используя 1-8 потоков. Но время не кажется правильным. Я получаю самое большое время, используя 1 поток (как и ожидалось), тогда время становится меньше. Но самое маленькое время, которое я получаю, это когда я использую 4 потока.

Вот пример, когда я использую массив 1000x1000.

Использование 1 потока ~ 9,62 с, Использование 2 потоков ~ 4,73 с, Использование 3 ~ 3,64 с, Использование 4 ~ 2,99 с, Использование 5 ~ 4,19 с, Использование 6 ~ 3,84, Использование 7 ~ 3,34 , Используя 8 ~ 3.12.

Вышеуказанные моменты времени, когда я использую pthreads. Когда я использую openmp, сроки меньше, но следуют той же схеме.

Я ожидал, что время сократится с 1 до 8 из-за четырехъядерного процессора? Я думал, что, поскольку есть 4 процессора с 2 ядрами в каждом, 8 потоков могут работать одновременно. Связано ли это с операционной системой, на которой работает сервер?

Также я тестировал те же программы на другом сервере, который имеет 7 двухъядерных процессоров AMD Opteron (tm) 8214 и работает под управлением Linux версии 2.6.18-194.3.1.el5. Там время, которое я получаю, это то, что я ожидал. Время уменьшается с 1 (самое большое) до 8 (самое маленькое время выполнения).

Программа правильно реализует Game of Life, используя как pthreads, так и openmp, я просто не могу понять, почему сроки похожи на пример, который я опубликовал. Итак, в заключение, мои вопросы:

1) Количество потоков, которые могут одновременно выполняться в системе, зависит от ядер процессора? это зависит только от процессора, хотя каждый процессор имеет более одного ядра? Это зависит от всех предыдущих и операционной системы?

2) Это связано с тем, как я делю массив 1000x1000 на количество потоков? Но если бы я это сделал, то код openmp не дал бы такой же шаблон времени?

3) По какой причине я могу получить такие сроки?

Это код, который я использую с openmp:

#define  Row 1000+2
#define Col 1000+2 int num; int (*temp)[Col]; int (*a1)[Col]; int (*a2)[Col];

int main() {
        int i,j,l,sum;
        int array1[Row][Col],array2[Row][Col];
        struct timeval tim;
        struct tm *tm;
        double start,end;
        int st,en;

           for (i=0; i<Row; i++)
                for (j=0; j<Col; j++)
                   {
                    array1[i][j]=0;
                    array2[i][j]=0;
                  }
        array1[3][16]=1;
        array1[4][16]=1;
        array1[5][15]=1;
        array1[6][15]=1;
        array1[6][16]=1;
        array1[7][16]=1;
        array1[5][14]=1;
        array1[4][15]=1;
        a1=array1;
        a2=array2;
        printf ("\nGive number of threads:");
        scanf("%d",&num);

        gettimeofday(&tim,NULL);
        start=tim.tv_sec+(tim.tv_usec/1000000.0); omp_set_num_threads(num);
        #pragma omp parallel private(l,i,j,sum)
        {

                printf("Number of Threads:%d\n",omp_get_num_threads());
                for (l=0; l<100; l++)
                        {
                        #pragma omp for
                        for (i=1; i<(Row-1); i++)
                        {
                                for (j=1; j<(Col-1); j++)
                                {  
                                        sum=a1[i-1][j-1]+a1[i-1][j]+a1[i-1][j+1]+a1[i][j-1]+a1[i][j+1]+a1[i+1][j-1]+a1[i+1][j]+a1[i+1][j+1];
                                        if ((a1[i][j]==1) && (sum==2||sum==3))
                                                a2[i][j]=1;
                                        else if ((a1[i][j]==1) && (sum<2))
                                                a2[i][j]=0;
                                        else if ((a1[i][j]==1) && (sum>3))
                                                a2[i][j]=0;
                                        else if ((a1[i][j]==0 )&& (sum==3))  
                                                a2[i][j]=1;
                                        else if (a1[i][j]==0)
                                                a2[i][j]=0;

                                }//end of iteration J
                        }//end of iteration I
                        #pragma omp barrier
                        #pragma omp single
                                {

                                        temp=a1;
                                        a1=a2;
                                        a2=temp;
                                }

                        #pragma omp barrier
                        }//end of iteration L

        }//end of paraller region
        gettimeofday(&tim,NULL);
         end=tim.tv_sec+(tim.tv_usec/1000000.0);
         printf("\nTime Elapsed:%.6lf\n",end-start);
        printf("all ok\n");
        return 0; }

СРОКИ с кодом openmp

а) Система с 7 двухъядерными процессорами Использование 1 потока ~ 7,72 с, Использование 2 потоков ~ 4,53 с, Использование 3 потоков ~ 3,64 с, Использование 4 потоков ~ 2,24 с, Использование 5 ~ 2,02 с, Использование 6 ~ 1,78 сек, используя 7 ~ 1,59 сек, используя 8 ~ 1,44 сек

б) Система с 4 двухъядерными процессорами Использование 1 потока ~ 9,06 с, Использование 2 потоков ~ 4,86 ​​с, Использование 3 потоков ~ 3,49 с, Использование 4 потоков ~ 2,61 с, Использование 5 ~ 3,98 с, Использование 6 ~ 3,53 сек, используя 7 ~ 3,48 сек, используя 8 ~ 3,32 сек

Выше время, которое я получаю.

Ответы [ 3 ]

0 голосов
/ 26 июля 2010

Вы пишете

Вышеуказанные моменты времени, когда я использую pthreads.Когда я использую openmp, временные рамки меньше, но следуют тому же шаблону.

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

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

Другой фактор, который важен при измерении параллельной масштабируемости вашей программы.это размер проблемы, которую вы используете.Как меняется ваша кривая производительности, когда вы пробуете сетку из 1414 x 1414 ячеек?Я ожидаю, что кривая будет ниже кривой для задачи на 1000 x 1000 ячеек и выровняется позже.

Для дальнейшего чтения Google для Закона Амдала и Закона Густафсона.

0 голосов
/ 08 апреля 2011

Может быть, ваш системный администратор контролирует, сколько потоков вы можете выполнять одновременно или сколько ядер вы используете.Я не знаю, возможно ли это на уровне sysadmin, но можно точно сказать процессу, что.

Или ваш алгоритм может быть с использованием кеша L2 плохо .Гиперпоточность или как она там называется теперь работает лучше всего, когда один поток делает что-то, что занимает много времени, а другой - нет.Доступ к памяти, не находящейся в кеше L2, является МЕДЛЕННЫМ, и поток, делающий это, будет зависать, пока ожидает.Это только один пример того, откуда приходит время для запуска нескольких потоков на одном ядре.Четырехъядерная шина памяти может позволять каждому ядру одновременно получать доступ к некоторой памяти, но не каждому потоку в каждом ядре.Если оба потока идут на оперативную память, то они в основном работают последовательно.Так что это может быть то, откуда ваши 4.

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

0 голосов
/ 25 июля 2010

Одна вещь, которую вы должны помнить, это то, что вы делаете это на архитектуре с общей памятью.Чем больше загрузок / хранилищ вы пытаетесь делать параллельно, тем больше у вас шансов столкнуться с конфликтом в отношении доступа к памяти, что является относительно медленной операцией.Так что в типичных приложениях по моему опыту не пользуйтесь более чем 6 ядрами.(Это анекдотично, я мог бы вдаваться в подробности, но я не чувствую необходимости печатать. Достаточно сказать, возьмите эти цифры с малейшей долей соли).ресурсы, если это возможно, посмотрите, что это влияет на вашу производительность.В противном случае, оптимизируйте то, что вы получили, и запомните следующее:

Бросание большего количества ядер в проблему не означает, что она пойдет быстрее.Как и в случае с налогообложением, существует кривая того, когда количество ядер начинает снижать производительность вашей программы.Найдите это «сладкое пятно» и используйте его.

...