今天是个好日子!
我正在进行分子动力学模拟,最近我开始尝试并行实现它。乍一看,一切看起来都很简单:在最耗时的循环前面编写#pragma omp parallel for 指令。但是碰巧的是,这些循环中的函数在数组上运行,或者更准确地说,在属于我的类的对象的数组上运行,该对象包含有关粒子系统和在该系统上的函数的所有信息,所以当我添加时在最耗时的循环之一之前的 pragma 指令,尽管我的 2 核 4 线程处理器已满载,但计算时间实际上增加了数倍。
为了解决这个问题,我编写了另一个更简单的程序。该测试程序执行两个相同的循环,一个是并行的,另一个是串行的。测量执行这两个循环所需的时间。结果让我感到惊讶:每当并行计算第一个循环时,其计算时间与串行模式相比减少了(分别为 1500 和 6000 毫秒),但第二个循环的计算时间急剧增加(15 000 对 6000 串行)。
我尝试使用 private() 和 firstprivate() 子句,但结果是一样的。在并行区域之前定义和初始化的每个变量都不应该自动共享吗?如果在另一个向量 vec2 上执行第二个循环的计算时间会恢复正常,但是为每次迭代创建一个新向量显然不是一种选择。我还尝试将 vec1 的实际更新放入 #pragma omp 关键区域,但这也不是什么好事。两者都没有帮助添加 Shared(vec1) 子句。
如果您能指出我的错误并展示正确的方法,我将不胜感激。
是否有必要将该 private(i) 放入代码中?
这是这个测试程序:
#include "stdafx.h"
#include <omp.h>
#include <array>
#include <time.h>
#include <vector>
#include <iostream>
#include <Windows.h>
using namespace std;
#define N1 1000
#define N2 4000
#define dim 1000
int main(){
vector<int>res1,res2;
vector<double>vec1(dim),vec2(N1);
clock_t t, tt;
int k=0;
for( k = 0; k<dim; k++){
vec1[k]=1;
}
t = clock();
#pragma omp parallel
{
double temp;
int i,j,k;
#pragma omp for private(i)
for( i = 0; i<N1; i++){
for(j = 0; j<N2; j++){
for( k = 0; k<dim; k++){
temp+= j;
}
}
vec1[i]+=temp;
temp = 0;
}
}
tt = clock();
cout<<tt-t<<endl;
for(int k = 0; k<dim; k++){
vec1[k]=1;
}
t = clock();
for(int g = 0; g<N1; g++){
for(int h = 0; h<N2; h++){
for(int y = 0; y<dim; y++){
vec1[g]+=h;
}
}
}
tt = clock();
cout<<tt-t<<endl;
getchar();
}
感谢您的时间!
PS我使用Visual Studio 2012,我的处理器是Intel Core i3-2370M。我的程序集文件分为两部分: