LINUX.ORG.RU

[openmp]распараллелить код

 


0

0

Есть кусок кода:

void FillRandom(double ** array, int ncol, int nrow)
{
	srand(time(0));
	for (int i = 0; i < nrow; ++i)
	{
		for (int j = 0; j < ncol; ++j)
			array[i][j]= (double)rand()/RAND_MAX*RAND_DIV;
	}
}

Задача его распараллелить с помощью openmp. Как? Я пытался разобраться, но все мои попытки только приводили к большему времени выполнения. Обычно ncol=nrow=1000.

★★★★★
void FillRandom(double ** array, int ncol, int nrow) 
{ 
   srand(time(0)); 
#pragma omp parallel for private(j)
   for (int i = 0; i < nrow; ++i) 
   { 
      for (int j = 0; j < ncol; ++j) 
         array[i][j]= (double)rand()/RAND_MAX*RAND_DIV; 
   } 
} 

Компилять, запускать так export OMP_NUM_THREADS=2*ncores; ./a.out

Только непонятно, что ты там параллелить хочешь, функция rand() слишком мало времени CPU забирает, чтобы эффект от распараллеливания был. Вот если там что-то миллисекунд 30-40 вычисляющееся будет — другое дело.

annoynimous ★★★★★
()
Ответ на: комментарий от tailgunner

Таки есть

int
rand ()
{
  return (int) __random ();
}


long int
__random ()
{
  int32_t retval;

  __libc_lock_lock (lock);

  (void) __random_r (&unsafe_state, &retval);

  __libc_lock_unlock (lock);

  return retval;
}
anonymous
()
Ответ на: комментарий от annoynimous

У меня занимает 1.7 сек на c2d 3.2MHz

В твоем примере имею error: 'j' has not been declared

Перенес объявление j выше.
Компиляция твоего кода вызывает увеличение времени выполнения в 10 раз.

Pavval ★★★★★
() автор топика
Ответ на: комментарий от Pavval

> У меня занимает 1.7 сек на c2d 3.2MHz

3.2MHz

Моя машина потребляет 12 тонн бензина на 100км.

У меня батарейка в телефоне на 3.6 киловольт.

Купи в магазине 3 тонны пива.

Смешно звучит?

P.S. Ты быдлошкольник с ГСМ?

anonymous
()
Ответ на: комментарий от Pavval

Объяви i и j до #pragma. Число потоков я обычно ставлю равным удвоенному числу процессоров.

Но вообще, как тебе верно сказали, если в функции rand() есть семафор, то все потоки все равно будут выполнять эту функцию по-одиночке. Тебе нужно тестить все на реентрабельных функциях как минимум.

annoynimous ★★★★★
()

/thread

Pavval ★★★★★
() автор топика

надо rand_r использовать с отдельным сидом для каждого потока

Reset ★★★★★
()
Ответ на: комментарий от annoynimous

> Объяви i и j до #pragma

Как раз внутри for'ов очень удобно их объявлять, сразу снимаются вопросы по тому кто из них private, а кто shared и лишнего мусора внутри #pragma не возникает.

Reset ★★★★★
()
Ответ на: комментарий от Reset

Да, ты прав, что-то я не подумал...

ТС, тогда напиши просто #pragma omp parallel for

annoynimous ★★★★★
()

Господа, я уже все написал, не стоит продолжать обсуждать (т.е. /thread)

Вот код:

void FillRandom(double ** array, int ncol, int nrow) 
{ 
   unsigned seed;
   #pragma omp parallel private(seed)
   {
       seed = time(0); 
       #pragma omp for
       for (int i = 0; i < nrow; ++i) 
       { 
          for (int j = 0; j < ncol; ++j) 
             array[i][j]= (double)rand_r(&seed)/RAND_MAX*RAND_DIV; 
       }
   } 
} 
Pavval ★★★★★
() автор топика
Ответ на: комментарий от Pavval

не люблю я много писать внутри pragma:

void FillRandom(double ** array, int ncol, int nrow)  
{  
   #pragma omp parallel
   { 
       unsigned seed = time(0);  
       #pragma omp for 
       for (int i = 0; i < nrow; ++i)  
       {  
          for (int j = 0; j < ncol; ++j)  
             array[i][j]= (double)rand_r(&seed)/RAND_MAX*RAND_DIV;  
       } 
   }  
}  
Reset ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.