编译具有不同预处理器变量值的函数的多个版本

Compiling multiple versions of a function with different preprocessor variable values

提问人:Sean Bone 提问时间:10/12/2023 更新时间:10/12/2023 访问量:46

问:

我有以下函数,它使用 OpenMP 进行并行:

Real3 MyThing::compute(...) {
   // Do some setup...

#pragma omp parallel num_threads(OMP_THREADS)
    {
        // Local variables...
#pragma omp for nowait
        for (...) { ... }
#pragma omp critical
        { ... }
    }

    // Wrap up and return
}

其中使用的线程数可以在编译时由预处理器变量确定。OMP_THREADS

由于问题大小是在配置文件中确定的,因此仅在运行时才知道。因此,我想为 的多个值编译此函数(并且一个根本没有 OMP),然后有一个运行时条件来决定要运行哪个版本,例如:OMP_THREADS

if (mode == "ompx4") {
    return compute_omp4(...);
} else if (mode == "ompx8") {
    return compute_omp8(...);
} else {
    return compute_serial(...);
}

显然,我可以通过多次复制粘贴整个函数并在每个函数中硬编码不同的值来做到这一点,但由于这是一个相当大的函数,因此这并不理想。OMP_THREADS

通常我会对模板变量做一些类似的事情,但我认为我不能那样设置。关于如何以合理紧凑的形式制作它的任何建议?num_threads

C++ OpenMP 预处理器

评论

0赞 Paul Sanders 10/12/2023
平台?MSVC有,但我不知道它在这里是否有效_pragma
4赞 Daniel Langr 10/12/2023
在编译时指定线程数的原因是什么?为什么不简单地让它在运行时决定,并且只有一个函数可以处理任意数量的线程呢?无论如何,您也可以使用(非类型)模板参数作为 in 的“参数”。OMP_NUM_THREADSnum_threadspragma parallel
1赞 PierU 10/12/2023
将所需数量的线程作为唯一函数的参数传递并在子句中使用它有什么问题?compute()NUM_THREADS()
0赞 Sean Bone 10/12/2023
@PaulSanders Linux,使用 GCC 编译
1赞 Daniel Langr 10/13/2023
@SeanBone 你对这里的预处理器是正确的,它很可能不起作用。但是在编写时,也接受运行时值。如果你想让用户独立地控制线程数,你也可以为它创建一个单独的环境变量。这是实践中的常见解决方案。例如,OpenBLAS 有 .num_threadsOMP_NUM_THREADSOPENBLAS_NUM_THREADS

答:

0赞 Sean Bone 10/12/2023 #1

事实证明,该子句也可以使用运行时值进行设置。出于某种原因,我脑海中浮现了它,它必须在编译时设置。num_threads

感谢那些在评论中帮助我的人!