openmp没有利用所有线程

时间:2015-04-11 16:06:10

标签: c multithreading openmp

我使用OpenMP在C语言中编写了并行程序。

我想控制程序正在使用的线程数。

我正在使用系统:

  • CentOS 6.5版(最终版)
  • icc版本14.0.1(gcc版本4.4.7兼容性)
  • 2x Intel(R)Xeon(R)CPU E5-2620 0 @ 2.00GHz

我跑的节目:

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

double t1[TABLE_SIZE];
double t2[TABLE_SIZE];

int main(int argc, char** argv) {

    omp_set_dynamic(0);
    omp_set_nested(0);
    omp_set_num_threads(NUM_OF_THREADS);

    #pragma omp parallel for default(none) shared(t1, t2) private(i)
    for(i=0; i<TABLE_SIZE; i++) {
        t1[i] = rand();
        t2[i] = rand();
    }

    for(i=0; i<NUM_OF_REPETITION; i++) {
        test1(t1, t2);
    }
}

void test1(double t1[], double t2[]) {
    int i;
    double result;

    #pragma omp parallel for default(none) shared(t1, t2) private(i) reduction(+:result)
    for(i=0; i<TABLE_SIZE; i++) {
        result += t1[i]*t2[i];
    }
}

我正在运行脚本,在编译时设置TABLE_SIZE(2500,5000,100000,1000000),NUM_OF_THREADS(1-24),NUM_OF_REPETITION(50000为50k,100000为100k,1000000为1M)。 问题是计算机没有使用所有时间提供的所有线程。 似乎问题依赖于TABLE_SIZE。

例如,当我使用TABLE_SIZE = 2500编译代码时,一切正常,直到NUM_OF_THREADS = 20。然后发生了一些奇怪的事情。当我设置NUM_OF_THREADS = 21时,程序只使用18个线程(我观察htop以查看正在运行的线程数)。当我设置NUM_OF_THREADS = 23和NUM_OF_REPETITION = 100k时,它使用18个线程,但如果我在NUM_OF_THREADS = 23时将NUM_OF_REPETITION更改为1M,则使用19个线程。

当我将TABLE_SIZE更改为5000时,异常从18个线程开始。我设置NUM_OF_THREADS = 18,并且在NUM_OF_REPETITION = 1M时,程序仅使用17个线程。当我设置NUM_OF_THREADS = 19和NUM_OF_REPETITION = 100k或1M时,它仅使用17个线程。如果我将NUM_OF_THREADS更改为24,则程序在NUM_OF_REPETITION = 50k时使用20个线程,在NUM_OF_REPETITION = 100k时使用22个线程,在NUM_OF_REPETITION = 1M时使用23个线程。

这种不一致性随着TABLE_SIZE的增加而不断变化。 TABLE_SIZE越大(更低的NUM_OF_THREADS),就会出现不一致。

在这篇(OpenMP set_num_threads() is not working)帖子中,我读到omp_set_num_threads()设置了程序可以使用的线程的上限。正如你所看到的,我已经禁用了动态团队,程序仍未使用所有线程。如果我设置环境变量OMP_NUM_THREADS和OMP_DYNAMIC也无济于事。

所以我去阅读一些OpenMP规范3.1。它说程序应该使用omp_set_num_threads()设置的线程数。此外,omp_get_max_threads()函数返回24个可用线程。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方案。我设置了KMP_AFFINITY环境变量。如果我将变量设置为“compact”或“scatter”并不重要(我现在只对使用所有线程感兴趣)。

这是文档必须说的(https://software.intel.com/en-us/articles/openmp-thread-affinity-control):

  

OpenMP线程和关联性有两个注意事项:首先,确定要使用的线程数,其次,如何将线程绑定到特定的处理器核心。

     

如果没有为KMP_AFFINITY设置值,则允许OpenMP运行时为您选择关联。选择的值取决于CPU架构,并且可能会根据对该架构的各种应用程序最有效的亲和力而改变。

另一个来源(https://software.intel.com/en-us/node/522691):

  

亲和力类型:

     

type = none(默认)

     

不将OpenMP *线程绑定到特定的线程上下文;但是,如果操作系统支持affinity,则编译器仍使用OpenMP *线程关联接口来确定机器拓扑。

所以我想因为我没有设置KMP_AFFINITY,所以OpenMP运行时为它的知识设置了最有效的亲和力。如果我错了,请纠正我。