用于并行计算的C ++ + openmp:如何在visual studio中进行设置?

时间:2012-05-30 12:52:00

标签: c++ parallel-processing openmp

我有一个c ++程序,它创建一个对象,然后调用这个对象的2个函数,它们彼此独立。所以它看起来像这样:

Object myobject(arg1, arg2);
double answer1 = myobject.function1();
double answer2 = myobject.function2();

我希望这两个计算并行运行以节省计算时间。我已经看到这可以使用openmp完成,但无法弄清楚如何设置它。我发现的唯一例子是向不同的核心发送相同的计算(例如“hello world!”),输出是“hello world!”的2倍。在这种情况下我该怎么做?

我在Visual Studio 2005中使用Windows XP。

3 个答案:

答案 0 :(得分:3)

您应该查看OpenMP的sections结构。它的工作原理如下:

#pragma omp parallel sections
{
   #pragma omp section
   {
      ... section 1 block ...
   }
   #pragma omp section
   {
      ... section 2 block ...
   }
}

两个块可能并行执行,因为团队中至少有两个线程,但由实现来决定执行每个部分的方式和位置。

使用OpenMP任务有一个更清晰的解决方案,但它要求您的编译器支持OpenMP 3.0。 MSVC仅支持OpenMP 2.0(即使在VS 11中!)。

您应该在项目的设置中明确启用OpenMP支持。如果从命令行进行编译,则选项为/openmp

答案 1 :(得分:1)

如果您的代码所需的内存不是很多,您也可以使用MPI库。为此,首先从本教程Compiling MPI Programs in Visual Studio在Visual Studio上安装MPI 或者从这里开始:MS-MPI with Visual Studio 2008 使用这个mpi hello世界代码:

#include<iostream>
#include<mpi.h>
using namespace std;

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

int mynode, totalnodes;

MPI_Init(&argc, &argv); 
MPI_Comm_size(MPI_COMM_WORLD, &totalnodes);
MPI_Comm_rank(MPI_COMM_WORLD, &mynode);

cout << "Hello world from process " << mynode;
cout << " of " << totalnodes << endl;

MPI_Finalize();
return 0;
}

为您的基本代码,添加您的函数并使用此示例if语句声明每个进程的作业:

if(mynode== 0 ){function1}
if(mynode== 1 ){function2}

function1和function2可以是你喜欢同时执行的任何事情;但请注意这两个功能彼此独立。 而已!

答案 2 :(得分:0)

第一部分是使用Visual Studio 2005启动和运行OpenMP,这是相当陈旧的;它需要做一些事情,但它在this question的答案中有描述。

一旦完成,如果您有两种真正完全独立的方法,那么执行这种简单形式的任务并行化相当容易。注意限定符;如果方法是读取相同的数据,那没关系,但是如果他们正在更新其他方法使用的任何状态,或者调用任何其他例程,那么事情会破裂。

只要这些方法完全独立,你可以使用sections来实现这些(tasks实际上是更现代的OpenMP 3.0方式,但是你可能无法获得OpenMP 3.0对这种旧编译器的支持);你也会看到人们滥用并行for循环来实现这一点,这至少具有让你控制线程分配的优势,所以尽管我不能真正推荐它,但我还是把它包含在这里:

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

int f1() {
    int tid = omp_get_thread_num();
    printf("Thread %d in function f1.\n", tid);
    sleep(rand()%10); 
    return 1;
}

int f2() {
    int tid = omp_get_thread_num();
    printf("Thread %d in function f2.\n", tid);
    sleep(rand()%10); 
    return 2;
}


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

    int answer;
    int ans1, ans2;

    /* using sections */
#pragma omp parallel num_threads(2) shared(ans1, ans2, answer) default(none)
    {
#pragma omp sections 
        {
#pragma omp section
            ans1 =  f1();

#pragma omp section
            ans2 =  f2();
        }  

#pragma omp single
        answer = ans1+ans2;

    }  

    printf("Answer = %d\n", answer);

    /* hacky appraoch, mis-using for loop */
    answer = 0;
#pragma omp parallel for schedule(static,1) num_threads(2) reduction(+:answer) default(none)
    for (int i=0; i<2; i++)  {    
        if (i==0)
            answer += f1();
        if (i==1)
            answer += f2();
    }

    printf("Answer = %d\n", answer);

    return 0;
}

运行此功能

$  ./sections 
Thread 0 in function f1.
Thread 1 in function f2.
Answer = 3
Thread 0 in function f1.
Thread 1 in function f2.
Answer = 3