OpenMP是一种跨平台的多线程API,它允许使用特殊的编译器指令进行细粒度的任务并行化和同步。
科学计算领域的大多数人在共享内存并行化方面都使用 OpenMP 作为准标准。 是否有任何理由(除了可读性之外)在 pthreads 上使用 OpenMP?拉...
我有一个简单的 C++ 程序,什么也不做: int main() { 返回 0; } 我正在尝试使用以下命令完全静态地构建该程序: g++ -o c c.cc -静态 一切正常...
与 Windows、MSVC 和 OpenMP 的线程关联性
我想将代码中的线程绑定到每个物理核心。 使用 GCC,我已经使用 sched_setaffinity 成功完成了此操作,因此我不再需要设置导出 OMP_PROC_BIND=true。 我想做...
为什么在 openMP 并行 for 循环中创建 C++ 向量会导致其速度显着减慢?
我试图在使用 openMP 的并行 for 循环内初始化 std::vector ,但这会导致它花费的时间比串行循环花费的时间要多得多。 这是一个例子...
我对 OpenMP 还比较陌生。掌握了窍门,但偶然发现了一些我需要解释的事情。 可能像大多数用户一样,我最常见的用例是: #pragma omp 用于并行 对于(整数...
我正在尝试并行化以下程序,但不知道如何减少数组。我知道不可能这样做,但是有其他选择吗?谢谢。 (我在 m 上添加了减少,这是...
我在过去的许多项目中都使用过 OpenMP。另外,我还在一些开源项目中编写了 CUDA 和 OpenCL GPU 代码。 我经常听说 OpenMP 5 添加了对 NV 的支持...
我的问题有点类似于这个:How to use lock in OpenMP? 从某种意义上说,他们的答案有点回答了我的问题,但还不够好。 我正在尝试实现一个简单的工作窃取
在OpenMP(C/C++)中,当要应用数组缩减时,每个线程的初始私有数组是什么? [已关闭]
OpenMP-4.5 支持原始数组缩减(+:array[:]),类似于之前的标量缩减缩减(+:scalar)。 有大量关于如何减少标量的信息
在OpenMP(C++)中,当要应用数组缩减时,每个线程的初始私有数组是什么?
是每个线程的初始私有数组 (a) 并行块上方定义的原始数组的副本或 (b) 全零数组?
目标和目标数据之间的差异?如何在没有团队指令的情况下进行团队/线程配置?
我有 2 个关于新 OpenMP 4.0 的问题。 第一个是我无法理解目标和目标数据之间有什么区别?根据规范目标数据创建新数据
我用 C 语言开发了这个函数来读取每行一个单词组成的文件,就像标准的单词列表一样。 功能已经优化到合理的程度了,但是我想知道是否...
我目前正在使用 LLVM/clang-16(从 github 存储库构建)进行 OpenMP 卸载。使用 clang 中的内置分析工具(使用 LIBOMPTARGET_P 等环境变量...
我正在使用 OpenMP 并行化(内部)循环。 每次迭代的工作量不是很大,因此更多的线程会带来重要的开销。 因此我将循环安排为静态(a...
我一直在关注“一个周末的光线追踪”教程系列,这在学习光线追踪方面似乎相对规范。 我一直在尝试使用 OpenMP 加速代码...
我需要帮助并行化这段代码,我知道在循环内使用 !$omp 并行会减慢速度,所以我必须将其放在外部,但这样做会创建错误值 !$omp 并行...
我很早以前在编写c++程序时就使用过OpenMP。 突然,我的脑海中浮现出一个问题。 “OpenMP 如何知道嵌套了多少个循环实例?” 编译器是否显式计算?
我正在尝试使用任务来调整 C + OpenMP 中块矩阵乘法的代码(示例 5.3.5)。 此代码使用依赖数组部分说明了任务依赖关系。 这是摘录...
我是 Openmp 编程新手,我有一个关于递归任务并行性的问题 让我们考虑一下这个演示 C 代码: #包括 #包括 #包括 我是 Openmp 编程新手,我有一个关于递归任务并行性的问题 让我们考虑一下这个演示 C 代码: #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <omp.h> struct timeval t1, t2; void recursive_task(int level) { //printf("%d\n", level); if (level == 0){ usleep(1000); return; } else { recursive_task(level-1); #pragma omp task { recursive_task(level-1); } #pragma omp task { recursive_task(level-1); } #pragma omp taskwait recursive_task(level-1); } } int main() { double time; gettimeofday(&t1, 0); #pragma omp parallel { #pragma omp single { recursive_task(7); } } gettimeofday(&t2, 0); time = (double)((t2.tv_sec - t1.tv_sec) * 1000000 + t2.tv_usec - t1.tv_usec) / 1000000; printf("%.4f\n", time); return 0; } 每一级递归执行 4 次调用,其中只有第二次和第三次调用可以实际并行运行。 现在我尝试了这个不同的版本: #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <omp.h> struct timeval t1, t2; void recursive_task(int level) { //printf("%d\n", level); if (level == 0){ usleep(1000); return; } else { #pragma omp task if(0) { recursive_task(level-1); #pragma omp task { recursive_task(level-1); } recursive_task(level-1); #pragma omp taskwait recursive_task(level-1); } } } int main() { double time; gettimeofday(&t1, 0); #pragma omp parallel { #pragma omp single { recursive_task(7); } } gettimeofday(&t2, 0); time = (double)((t2.tv_sec - t1.tv_sec) * 1000000 + t2.tv_usec - t1.tv_usec) / 1000000; printf("%.4f\n", time); return 0; } 执行似乎也遵循正确的调用顺序(我认为这与 if(0) 子句有关)。 然而令我惊讶的是第二个比第一个更快。我使用 8 个线程执行,第一种方法需要 4.4 秒,第二种方法需要 3.4 秒! 使第二个代码更快的主要区别是什么? 重点是影响#pragma omp taskwait等待当前任务的子任务完成,当有使用#pragma omp task if(0)创建的任务时,当前任务不一样。这意味着“不”拥有较晚的指令会导致“过度同步”,从而导致更高的执行时间(当然是由于并行性较低)。事实上,在这种情况下, #pragma omp taskwait 指令会等待更多任务(尤其是没有 if(0) 的真实任务。 2 个级别的示例 为了更好地理解发生了什么,我们可以分析该函数在级别 2 上到底做了什么(并将延迟增加到 10_000,以便我们可以在运行时看到任何差异)。这是扁平化代码: void recursive_task_level2() { #pragma omp task if(0) { #pragma omp task if(0) { usleep(10000); #pragma omp task usleep(10000); usleep(10000); #pragma omp taskwait usleep(10000); } #pragma omp task // <----- [A] WAITED TASK { #pragma omp task if(0) { usleep(10000); #pragma omp task usleep(10000); usleep(10000); #pragma omp taskwait usleep(10000); } } #pragma omp task if(0) // <----- [B] IMPORTANT ONE { usleep(10000); #pragma omp task usleep(10000); usleep(10000); #pragma omp taskwait // <----- [C] usleep(10000); } #pragma omp taskwait #pragma omp task if(0) { usleep(10000); #pragma omp task usleep(10000); usleep(10000); #pragma omp taskwait usleep(10000); } } } 这个想法是:如果 [B] 存在,那么 [C] 不会等待 [A],因为它不再是子任务;但是,如果 [B] 不存在,则 [C] 等待 [A],即等待 10 毫秒之前。通过在有/没有 [B] 以及有/没有所有其他 #pragma omp task if(0) 的情况下运行此代码来确认此效果。在这种情况下,唯一重要的指令是 [B],而注释 [B] 确实会增加执行时间 10 毫秒(92 毫秒 vs 102 毫秒)。这证明了假设是正确的。随着级别的增加,由于过度同步,并行量会大大减少,并且额外的时间也会在关键路径上累积(当然是指数级的),从而导致巨大的执行开销。
我不明白为什么在这段代码中只有线程0有n = 1,而其他线程有n = 0并且共享n: int main() { 整数n,tid; #pragma omp 并行共享(n) 私有(tid) { ...