omp_set_num_threads我应该每次都使用它还是可以设置一次?

时间:2014-03-10 21:36:29

标签: c openmp

我有一个程序可以调用大约100个函数 - 我想为每个函数使用omp_set_num_threads。我应该在每次调用ith功能之前使用它吗?或者我可以使用它一次,让我们说在int main(int argc, char **argv)之后,它将用于每个函数调用吗?

看起来像这样:

omp_set_num_threads(val);
if(call_me_i)
   call_ith_function;


omp_set_num_threads(val);
if(call_me_i+1)
   call_ith+1_function;
...

3 个答案:

答案 0 :(得分:2)

简短回答:您只需要设置一次线程数,除非您想稍后更改它。一旦设定,就会“记住”。

听起来我觉得你有各自的函数,其中包含一些并行代码,并且你想确保它们确实并行运行。如果您有大量if语句,通常需要考虑switch

omp_set_num_threads(val); //<<< set just once
switch(whatFunction) {
  case fun1:
    callFunction1();
    break;
  case fun2:
    callFunction2();
    break;
  default:
    // etc
}

void callFunction1() {
  int ii;
  #pragma omp parallel
  // <<<< just this for loop will run in parallel >>>>>
  for(ii=0; ii<100; ii++) {
    // do stuff
  }
  printf("done\n"); printf("really done\n"); printf("totally done\n"); // << NOT in parallel
}

void callFunction2() {
  int jj;
  for(jj=0; jj<100; jj++) {
    // do stuff
  }  // <<<< this loop does NOT run in parallel since there is no #pragma in front of it
}

答案 1 :(得分:2)

你永远不应该使用它!

一旦你使用它,你就会阻止你的代码在别人的机器上运行,或者在你明年或之后购买的机器上运行(此时你会忘记你强迫它)。

如果您使用英特尔编译器,它将默认使用进程可用的所有硬件线程(即,不会从进程的亲和力掩码中屏蔽掉),而无需您执行任何操作。 Gcc可能表现不同,但肯定会尊重OMP_NUM_THREADS环境变量,这是选择要使用的线程数的更好位置。

将当前机器的知识构建到代码中只是一个坏主意,因为(正如我们现在所知),代码的寿命比硬件长得多。

答案 2 :(得分:0)

你应该更清楚,但我会试着解释一下它是如何运作的。

我的cpu看起来像这样:

Architecture:          i686
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    2
Core(s) per socket:    2
Socket(s):             1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 28
Stepping:              10
CPU MHz:               1000.000
BogoMIPS:              3325.16
Virtualization:        VT-x
L1d cache:             24K
L1i cache:             32K
L2 cache:              512K

好吧,我有4个逻辑cpu。这意味着 omp_get_max_threads()应返回4.

这是我的示例代码:

#include<omp.h>
#include<iostream>

using namespace std;

int main()
{
  cout << omp_get_num_threads() << " " << omp_get_max_threads() << endl;
  omp_set_num_threads(omp_get_max_threads());
  cout << omp_get_num_threads() << " " << omp_get_max_threads() << endl;
  #pragma omp parallel
  {
    #pragma omp single
    cout << omp_get_num_threads() << " " << omp_get_max_threads() << endl;
    cout << "x" << endl;
  }
  return 0;
}

及其输出:

1 4
1 4
4 4
x
x
x
x

正如您所看到的, omp_set_num_threads()在开始时被调用过一次。然而,此调用并不意味着你从那时开始并行运行。

要并行运行指令,您需要使用 #pragma omp parallel 。如果它位于 {...} 部分之前,则整个部分将并行运行。如果这是在正常行之前,它将仅影响此行。第二种方法出现在 #pragma omp single 之后。我称之为,因为我不希望每个线程都打印下一行。我只想要一个人来打印它。

无论如何,你需要的只是做以下事情:

omp_set_num_threads(omp_get_max_threads());

#pragma omp parallel
{
   if(call_me_i)
      call_ith_function;    

   if(call_me_i+1)
      call_ith+1_function;
}