我正在学习OpenMP,并遇到了以下示例:
#pragma omp parallel shared(n,a,b,c,d,sum) private(i)
{
#pragma omp for nowait
for (i=0; i<n; i++)
a[i] += b[i];
#pragma omp for nowait
for (i=0; i<n; i++)
c[i] += d[i];
#pragma omp barrier
#pragma omp for nowait reduction(+:sum)
for (i=0; i<n; i++)
sum += a[i] + c[i];
} /*-- End of parallel region --*/
Run Code Online (Sandbox Code Playgroud)
在最后一个for循环中,有一个nowait和一个reduction子句.它是否正确?减少条款不需要同步吗?
我一直在使用openmp框架进行一些实验,发现了一些奇怪的结果,我不知道我知道如何解释.
我的目标是创建这个巨大的矩阵,然后用值填充它.为了从多线程环境中获得性能,我将代码的某些部分作为并行循环.我在一台配有2个四核xeon处理器的机器上运行它,所以我可以安全地在那里放置8个并发线程.
一切都按预期工作,但由于某种原因,实际分配矩阵行的for循环在仅运行3个线程时具有奇怪的峰值性能.从那以后,添加更多线程只会让我的循环花费更长时间.8个线程实际上只需要一个线程就可以获得更多时间.
这是我的并行循环:
int width = 11;
int height = 39916800;
vector<vector<int> > matrix;
matrix.resize(height);
#pragma omp parallel shared(matrix,width,height) private(i) num_threads(3)
{
#pragma omp for schedule(dynamic,chunk)
for(i = 0; i < height; i++){
matrix[i].resize(width);
}
} /* End of parallel block */
Run Code Online (Sandbox Code Playgroud)
这让我想知道:在多线程环境中调用malloc(我想是矢量模板类的resize方法实际调用的)时是否存在已知的性能问题?我在一个多线程环境中发现了一些关于释放堆空间性能损失的文章,但没有具体说明在这种情况下分配新空间.
举一个例子,我将下面的图表显示循环完成所需的时间作为分配循环的线程数的函数,以及一个只读取来自这个巨大矩阵的数据的正常循环稍后的.


两次使用gettimeofday函数测量并且似乎在不同的执行实例中返回非常相似和准确的结果.那么,任何人都有一个很好的解释?
因此,在SO和整个互联网上,如何使OpenMP易于使用的#pragma指令与C++同样易于使用的STL容器配合使用,会有很多困惑和沮丧.
每个人都有关变通的STL会谈vector,但对于非随机接入/双向容器,如map,list,set,等?
我遇到了这个问题并设计了一个非常简单明了的解决方法.我在这里介绍STL map,但它显然是可推广的.
串口版:
for (std::map<A,B>::iterator it = my_map.begin();
it != my_map.end();
++it)
{ /* do work with it */ }
Run Code Online (Sandbox Code Playgroud)
我提出的将OpenMP与STL一起使用的解决方案map:
//make an array of iterators.
int loop_length = my_map.size();
std::map<A,B>::iterator loop_array[ loop_length ];
std::map<A,B>::iterator allocate_it = my_map.begin();
for (int j=0; j<loop_length; ++j)
loop_array[j] = allocate_it++;
// now you can use OpenMP as usual:
#pragma omp parallel for
for (uint j=0; j<loop_length; ++j)
{ /* …Run Code Online (Sandbox Code Playgroud) 我有一个可以使用schedule(static)或schedule(dynamic, 10)根据条件执行的for循环.目前,我的代码不是DRY(不要重复自己),为了适应以前的功能,它有以下重复:
boolean isDynamic; //can be true or false
if(isDynamic){
#pragma omp parallel for num_threads(thread_count) default(shared) private(...) schedule(dynamic, 10)
for(...){
//for code inside
}
}else{
#pragma omp parallel for num_threads(thread_count) default(shared) private(...) schedule(static)
for(...){
//SAME for code inside, in fact, this is the EXACT same for as before
}
}
Run Code Online (Sandbox Code Playgroud)
阅读完这些主题之后,我注意到openMP有一个#if(expression)pragma:
但是虽然我看到很多人遇到了我的问题,但似乎缺乏一般的解决方案.最好的解决方案是将for循环的主体转换为函数,然后调用函数,但这个解决方案对我来说还不够好.
所以我想知道,OpenMP有一种#if(expression) else实用主义吗?就像是:
#if(isDynamic )pragma omp parallel for num_threads(thread_count) default(shared)
private(...) schedule(dynamic, 10)
else …Run Code Online (Sandbox Code Playgroud) 我正在创建一个基本的素数检查器,基于C - 确定一个数字是否为素数 ,但是使用OpenMP.
int isPrime(int value)
{
omp_set_num_threads(4);
#pragma omp parallel for
for( int j = 2; j * j <= value; j++)
{
if ( value % j == 0) return 0;
}
return value;
}
Run Code Online (Sandbox Code Playgroud)
使用-fopenmp进行编译时,GCC版本4.7.2 出错,说明invalid controlling predicatefor循环.
看起来这个错误是由for循环中的j平方引起的.有没有办法解决这个问题,仍然可以从算法中获得所需的输出?
想象一下经典的OMP任务:
using namespace std;
int main() {
vector<double> v;
// generate some data
generate_n(back_inserter(v), 1ul << 18,
bind(uniform_real_distribution<double>(0,1.0), default_random_engine { random_device {}() }));
long double sum = 0;
{
#pragma omp parallel for reduction(+:sum)
for(size_t i = 0; i < v.size(); i++)
{
sum += v[i];
}
}
std::cout << "Done: sum = " << sum << "\n";
}
Run Code Online (Sandbox Code Playgroud)
我无法想出如何报告进度.毕竟,OMP正在为我处理团队线程之间的所有协调,而我没有一个全局状态.
我可能会使用常规std::thread并从那里观察一些共享变量,但是没有更多的"omp-ish"方法来实现这一目标吗?
我正在尝试使用clang(3.7.0)在运行linux mint的笔记本电脑上设置一个OpenMP项目.
现在我已经读过OpenMP不会立即得到支持所以我按照本教程https://clang-omp.github.io/将openMP集成到了clang中.
我已经克隆了源代码,设置了环境变量并将-fopenmp标志设置为我的项目,但是在构建时我仍然收到错误"致命错误:'omp.h'文件未找到".
我的猜测是我设置了环境变量错误.有没有办法检查我是否把它们放在正确的位置?我刚刚将它们复制到.bashrc文件中.
编辑:当我运行$ locate omp.h时,我得到:
/usr/include/re_comp.h
/usr/include/linux/ppp-comp.h
/usr/include/linux/seccomp.h
/usr/include/net/ppp-comp.h
/usr/include/openssl/comp.h
/usr/lib/gcc/x86_64-linux-gnu/4.8/include/omp.h
/usr/lib/perl/5.18.2/CORE/regcomp.h
/usr/src/linux-headers-3.13.0-24/arch/arm/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/microblaze/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/mips/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/powerpc/include/uapi/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/s390/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/sh/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/sparc/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/arch/x86/include/asm/seccomp.h
/usr/src/linux-headers-3.13.0-24/include/linux/ppp-comp.h
/usr/src/linux-headers-3.13.0-24/include/linux/seccomp.h
/usr/src/linux-headers-3.13.0-24/include/net/ipcomp.h
/usr/src/linux-headers-3.13.0-24/include/uapi/linux/ppp-comp.h
/usr/src/linux-headers-3.13.0-24/include/uapi/linux/seccomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/seccomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/crypto/pcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/inet/ipcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/inet6/ipcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/isdn/ppp/bsdcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/ppp/bsdcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/config/xfrm/ipcomp.h
/usr/src/linux-headers-3.13.0-24-generic/include/linux/ppp-comp.h
/usr/src/linux-headers-3.13.0-24-generic/include/linux/seccomp.h
Run Code Online (Sandbox Code Playgroud)
这是我的makefile:
# Requires the following project directory structure:
# /bin
# /obj
# /src
# Use 'make remove' to clean up the whole project
# Name of target file
TARGET = main
CXX = clang++
CFLAGS = -std=c++11 \
-Weverything -Wall …Run Code Online (Sandbox Code Playgroud) 我已经从Debian Jessie和Fedora 24的基本存储库安装了clang 3.8.当我尝试使用clang ++编译一个简单的HelloWorld.cpp测试程序时,我传递了-fopenmp标志,在这两种情况下我都得到了同样的错误:
/ usr/bin/ld:找不到-lomp clang-3.8:错误:链接器命令失败,退出代码为1(使用-v查看调用)
我看到如果我改为传递-fopenmp = libgomp,它就可以了.但是,Clang OpenMP网站表示OpenMP运行时随Clang 3.8一起提供.那么,为什么它找不到默认的libomp库呢?我在系统的任何地方都看不到这个库.
我试图使用openmp与Apple clang,但无法使其工作.我从llvm下载并编译了openmp库.我的问题是,clang不承认-fopenmp旗帜.我收到以下错误:
clang: error: unsupported option '-fopenmp'
Run Code Online (Sandbox Code Playgroud)
我有Xcode和clang的第8版.任何帮助将非常感激.