Проблема работы с многопроцессорным программированием и открытием mp

Я посылаю вам игрушку о многопроцессорном программировании. программа работает хорошо или нет, я могу получить на 50% больше производительности. Однако, если я вхожу в # pragma parallel для программы, она больше не работает. Как улучшить работу? Как я могу узнать, сколько процессов я должен выполнить, чтобы получить максимальную производительность. Например, на 4-ядерном или 8-ядерном? :

#include <stdio.h>
#include <windows.h>
#include <process.h> 
#include <time.h>
#include <stdlib.h>

#define X 100000

char matrix[8000*X] ;
volatile long barrier = 0 ;

unsigned long long start[] ={ 0 , 1000*X+1 , 2000*X+1 , 3000*X+1 , 4000*X+1 , 5000*X+1, 7000*X+1 } ;
unsigned long long stop[] ={ 1000*X , 2000*X , 3000*X , 4000*X , 5000*X , 6000*X , 8000*X } ;

 void init( void *arg1 ) 
 {
 long i ;
 const long s0 = start[(ULONG_PTR)arg1];
 const long s1 = stop[(ULONG_PTR)arg1];

 // #pragma omp parallel for <------ *** with pragma does not work ! ***
 for (i= s0 ; i< s1 ; i++ )
 {
 matrix[i] = 0 ;
 }
 ++barrier ;
 }

long main()
{
 register long i , ZZZ;
 clock_t tempo0 ;
 clock_t tempo1 ;

 // ********************************************************#1
 printf( "Now in the main() function.\n" );
 tempo0 = clock();
 for (ZZZ=0;ZZZ<100;ZZZ++)
 {
 for ( i=0;i<8000*X;i++)
 matrix[i] = 0 ;
 }
 tempo1 = clock();
 printf ( "\nsequenziale <%lf>\n" , (******) tempo1-tempo0 );

 // return 0 ;
 // ******************************************************* #2
 tempo0 = clock();
 for (ZZZ=0;ZZZ<100;ZZZ++)
 { 
 barrier = 0 ;
 _beginthread( init, 0, (void*) 0 );
 _beginthread( init, 0, (void*) 1 );
 _beginthread( init, 0, (void*) 2 );
 _beginthread( init, 0, (void*) 3 );
 _beginthread( init, 0, (void*) 4 );
 _beginthread( init, 0, (void*) 5 );
 _beginthread( init, 0, (void*) 6 );
 _beginthread( init, 0, (void*) 7 );

 while ( barrier!=8) 
 ;
 }

 tempo1 = clock ();

 printf ( "\nthread <%lf>\n" , (******) tempo1-tempo0 );


}
</stdlib.h></time.h></process.h></windows.h></stdio.h>

заранее спасибо

1 ответ

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

for (ZZZ=0;ZZZ<100;ZZZ++)
{
 for ( i=0;i<8000*X;i++)
 matrix[i] = 0 ;
}

вы вызываете 100 * матрицу init до 0. Но в потоковом коде вы инициализируете матрицу до 0 только 1 раз!

Теперь для вашего вопроса о производительности.

На самом деле вы допустили несколько ошибок в способе масштабирования и почему в конце это не работает, когда вы раскомментируете #pragma omp parallel for.

Представьте, что у вас есть 8 ядер (1 поток на ядро), как в вашем примере. В вашей петле

for (ZZZ=0;ZZZ<100;ZZZ++)
{ 
 barrier = 0 ;
 _beginthread( init, 0, (void*) 0 );
 _beginthread( init, 0, (void*) 1 );
 _beginthread( init, 0, (void*) 2 );
 _beginthread( init, 0, (void*) 3 );
 _beginthread( init, 0, (void*) 4 );
 _beginthread( init, 0, (void*) 5 );
 _beginthread( init, 0, (void*) 6 );
 _beginthread( init, 0, (void*) 7 );

 while ( barrier!=8) 
 ;
}

8, и теперь, если вы раскомментируете свою директиву OpenMp в функции init, вы попросите openMP разделить задание каждой функции init на несколько (8) потоков.

Итак, теперь у вас теоретически поток 8x8 работает одновременно, но у вас всего 8 ядер. И Thats, почему это не работает. Производительность будет уменьшаться из-за всего переключения контекста протектора!

На самом деле, чтобы ответить на ваш последний вопрос: "Как я могу узнать, сколько процессов нужно запускать, чтобы получить лучшую производительность?",

  1. мы говорим о потоке, а не о процессах!
  2. Цикл ZZZ - это ваша более грубая гранулярность, поэтому цикл, в котором может использоваться openMp.
  3. OpenMP будет разделять ваши 100 итераций по вашему ядру 4, 8 16 и т.д. Бесплатно.

Поэтому я перепишу ваш код, как показано ниже:

tempo0 = clock();
#pragma omp parallel for
for (int z = 0 ; z < 8000*X ; z++)
{ 
matrix[z] = 0;
}
tempo1 = clock ();

У меня только 2 ядра, но без OpenMP, это заняло 630 тиков, и только 452 с 2 ядрами, и это автоматически спустится с большим ядром.

licensed under cc by-sa 3.0 with attribution.