我有一个用于N-queens计算的简单C程序。我使用OpenMP并行化它。现在我想执行串行和并行版本并计算加速。关键是我不想为串行代码创建新文件,或者只是将我的解决方案复制到没有OpenMP指令的新函数。我想要做的是,保留一个函数,并从主函数告诉何时将其作为序列执行,何时作为并行执行。我虽然使用预处理器,但我确定它是否可行,如果是,我怎样才能实现它。
void solve()
{
int i;
#if PARALLEL == 1
#pragma omp parallel for
#endif
for(i = 0; i < size; i++) {
int *queens = (int*)malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
int main()
{
...
#define PARALLEL 0
st_start = clock();
solve();
st_end = clock();
#define PARALLEL 1
pt_start = omp_get_wtime();
solve();
pt_end = omp_get_wtime();
...
}
答案 0 :(得分:1)
编辑:我想到了一种使用预处理器的方法。这解决了重复代码的问题,但代价是使编译和链接稍微复杂一些。它使用的特性是,如果编译器中未启用OpenMP,则忽略OpenMP结构。
#include <stdlib.h>
void setQueen(int* x, int y, int z) {
/*code*/
}
#if defined _OPENMP
void solve_parallel(const int size)
#else
void solve_serial(const int size)
#endif
{
int i;
#pragma omp parallel for
for(i = 0; i < size; i++) {
int *queens = (int*)malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
使用
进行编译gcc -O3 -c foo.c -o solve_serial
gcc -O3 -fopenmp -c foo.c solve_parallel
然后你可以在solve_serial和solve_parallel目标文件中使用类似于下面的函数指针和链接的主函数。
另一个选择是传递这样的线程数:
void solve(const int nthreads)
{
int i;
const int size = 10;
#pragma omp parallel for num_threads(nthreads)
for(i = 0; i < size; i++) {
int *queens = (int*)malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
然而,即使对于nthreads = 1,编译器也必须插入OpenMP结构,与不使用OpenMP进行编译相比,这会降低性能,因此可能会产生偏差的复杂性。
更公平的解决方案是使用和不使用OpenMP定义两个函数,然后使用函数指针数组(见下文)。当您想要比较优化的函数的多个变体时,这会更有用。
#include <stdlib.h>
#include <omp.h>
void solve_parallel(const int size)
{
int i;
#pragma omp parallel for
for(i = 0; i < size; i++) {
int *queens = (int*)malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
void solve_serial(const int size)
{
int i;
for(i = 0; i < size; i++) {
int *queens = (int*)malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
int main(void) {
const int size = 100;
int i;
double dtime[2];
void (*solve[2])(int);
solve[0] = solve_serial;
solve[1] = solve_parallel;
solve[1](size); /* run OpenMP once to warm it up */
for(i=0; i<2; i++) {
dtime[i] = omp_get_wtime();
solve[i](size);
dtime[i] = omp_get_wtime() - dtime[i];
}
return 0;
}
答案 1 :(得分:0)
不幸的是,你不能那样做。
预处理器只扫描您的代码并替换#stuff。 完成此操作后,编译器将编译代码,而#this
则没有所以在您发布的代码中,预处理器从第一行开始,如果PARALLEL为1则执行#pragma stuff代码,然后在main处继续,将PARALLEL定义为0,然后定义为1.
它不是从main开始然后进入solve();
您可能需要查看OpenMP: conditional use of #pragma
你可以尝试
void solve(int paral)
{
int i;
#pragma omp parallel for if (paral == 1)
for(i = 0; i < size; i++) {
int *queens = malloc(sizeof(int)*size);
setQueen(queens, 0, i);
free(queens);
}
}
我没有尝试过这段代码,但我对OMP没有经验,但是......
答案 2 :(得分:0)
调用预处理器,这是编译过程的第一部分;那就是所有的包含都被解决了,所有的前处理指令都被解决了,常量被它们的值取代等等......
因此,您无法使用预处理程序指令来执行运行时决策,您只能执行编译时决策。