我想验证当前编译器是否可以使用openmp支持构建.该应用程序已经部署在各种各样的unix系统上,其中一些可能有旧版本的OpenMP,我想测试重要的OpenMP功能.所以,我想构建一个包含一些OpenMP调用的测试源文件.
因此,我创建了一个非常简单的测试文件,并尝试使用CMake的try_compile函数.遗憾的是,它似乎没有正确应用-fopenmp链接器标志.有谁知道如何强制链接器标志或查看链接器标志是否被应用于任何地方?
来自CMakeLists.txt
try_compile(
HAVE_OPENMP
${APBS_ROOT}/src/config
${APBS_ROOT}/src/config/omp_test.c
CMAKE_FLAGS "-DCMAKE_C_FLAGS=-fopenmp -DCMAKE_EXE_LINKER_FLAGS=-fopenmp"
OUTPUT_VARIABLE TRY_COMPILE_OUTPUT
)
Run Code Online (Sandbox Code Playgroud)
来自omp_test.c
#include <stdio.h>
#include <omp.h>
int main()
{
int i;
int threadID = 0;
#pragma omp parallel for private(i, threadID)
for(i = 0; i < 16; i++ )
{
threadID = omp_get_thread_num();
#pragma omp critical
{
printf("Thread %d reporting\n", threadID);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果输出是
Change Dir: src/config/CMakeFiles/CMakeTmp
Run Build Command:/usr/bin/make "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: Entering directory `src/config/CMakeFiles/CMakeTmp'
/usr/bin/cmake -E cmake_progress_report /data/work/source/apbs/src/config/CMakeFiles/CMakeTmp/CMakeFiles 1
Building …Run Code Online (Sandbox Code Playgroud) OpenMP之间的区别是什么:
#pragma omp parallel sections
{
#pragma omp section
{
fct1();
}
#pragma omp section
{
fct2();
}
}
Run Code Online (Sandbox Code Playgroud)
并且:
#pragma omp parallel
{
#pragma omp single
{
#pragma omp task
fct1();
#pragma omp task
fct2();
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定第二个代码是否正确......
我开始使用C++使用OpenMP.
我有两个问题:
#pragma omp for schedule?dynamic和之间有什么区别static?请用例子说明.
在共享内存并行化方面,大多数科学计算人员使用OpenMP作为准标准.
是否有任何理由(除了可读性)使用OpenMP而不是pthreads?后者似乎更基本,我怀疑它可以更快更容易优化.
我将改造我的自定义图形引擎,以便它利用多核CPU.更确切地说,我正在寻找一个并行化循环的库.
在我看来,OpenMP和英特尔的Thread Building Blocks都非常适合这项工作.此外,Visual Studio的C++编译器和大多数其他流行的编译器都支持它们.这两个库看起来都非常简单易用.
那么,我应该选择哪一个?有没有人尝试过两个库,可以给我一些利弊和使用任何一个库的优点?另外,你最终选择了什么?
谢谢,
阿德里安
OpenMP标准仅考虑C++ 98(ISO/IEC 14882:1998).这意味着在C++ 03甚至C++ 11下没有标准的OpenMP支持用法.因此,任何使用C++> 98和OpenMP的程序都在标准之外运行,这意味着即使它在某些条件下工作,它也不太可能是可移植的,但绝对不能保证.
C++ 11具有自己的多线程支持,情况更糟,这很可能会在某些实现中与OpenMP发生冲突.
那么,将OpenMP与C++ 03和C++ 11一起使用有多安全?
可以安全地在一个相同的程序中使用C++ 11多线程和OpenMP但不交错它们(即在任何代码中没有传递给C++ 11并发特性的OpenMP语句,并且线程中没有C++ 11并发由OpenMP产生)?
我特别感兴趣的是我首先使用OpenMP调用一些代码,然后在相同的数据结构上使用C++ 11并发代码调用其他代码.
在OpenMP中使用时omp sections,将线程分配到这些块内的部分,或者将每个线程被分配给每个区段?
时间nthreads == 3:
#pragma omp sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
id=1
id=1
Run Code Online (Sandbox Code Playgroud)
但是当我执行以下代码时:
#pragma omp sections
{
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
#pragma omp section
{
printf ("id = %d, \n", omp_get_thread_num());
}
}
#pragma omp sections
{
#pragma omp section
{
printf ("id = …Run Code Online (Sandbox Code Playgroud) Valgrind线程错误检测工具Helgrind的文档,可在此处找到
警告说,如果你使用GCC来编译你的OpenMP代码,GCC的OpenMP运行时库(libgomp.so)将导致混乱的数据争用的误报,因为它使用原子机器指令和Linux futex系统调用而不是POSIX pthreads原语.它告诉您,您可以通过使用--disable-linux-futex配置选项重新编译GCC来解决此问题.
所以我尝试了这个.我使用配置选项编译并安装到本地目录(〜/ GCC_Valgrind/gcc_install)一个新的GCC版本4.7.0(撰写本文时的最新版本)--disable-linux-futex.然后我创建了一个没有可见数据竞争的小型OpenMP测试程序(test1.c):
/* test1.c */
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 2
int a[NUM_THREADS];
int main(void) {
int i;
#pragma omp parallel num_threads(NUM_THREADS)
{
int tid = omp_get_thread_num();
a[tid] = tid + 1;
}
for (i = 0; i < NUM_THREADS; i++)
printf("%d ", a[i]);
printf("\n");
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我编译了这个程序如下
~/GCC_Valgrind/gcc_install/bin/gcc -Wall -fopenmp -static -L~/GCC_Valgrind/gcc_install/lib64 -L~/GCC_Valgrind/gcc_install/lib -o test1 test1.c
Run Code Online (Sandbox Code Playgroud)
但是,我得到了30个误报数据竞赛报告! …
当使用openmp的parallel for construct分配和释放具有4个或更多线程的随机大小的内存块时,程序似乎开始在测试程序的运行时的后半部分泄漏大量内存.因此,它消耗的内存从1050 MB增加到1500 MB或更多,而无需实际使用额外的内存.
由于valgrind没有显示任何问题,我必须假设看起来像是内存泄漏实际上是内存碎片的强调效果.
有趣的是,如果2个线程分别进行10000次分配,则效果尚未显示,但如果4个线程分别进行5000次分配则显示效果很强.此外,如果分配的块的最大大小减少到256kb(从1mb),则效果会变弱.
重型并发能否强调碎片那么多?或者这更可能是堆中的错误?
构建演示程序是为了从堆中获取总共256 MB的随机大小的内存块,进行5000次分配.如果达到内存限制,则首先分配的块将被释放,直到内存消耗低于限制.执行5000次分配后,将释放所有内存并结束循环.所有这些工作都是针对openmp生成的每个线程完成的.
这种内存分配方案允许我们预计每个线程的内存消耗约为260 MB(包括一些簿记数据).
由于这是您可能想要测试的内容,您可以使用dropbox中的简单makefile下载示例程序.
按原样运行程序时,您应该至少有1400 MB的RAM可用.您可以随意调整代码中的常量以满足您的需求.
为完整起见,实际代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <deque>
#include <omp.h>
#include <math.h>
typedef unsigned long long uint64_t;
void runParallelAllocTest()
{
// constants
const int NUM_ALLOCATIONS = 5000; // alloc's per thread
const int NUM_THREADS = 4; // how many threads?
const int NUM_ITERS = NUM_THREADS;// how many overall repetions
const bool USE_NEW = true; // …Run Code Online (Sandbox Code Playgroud) 我在尝试编译项目时遇到以下错误:( fortran,使用gfortran)
未定义的引用`omp_get_max_threads_'
未定义的引用`omp_get_thread_num_'
问题是,我的GCC版本是4.4.3,这是为了支持OpenMP.