使用 OpenMP 进行缩减:线性合并或日志(线程数)合并

2023-12-07

我有一个关于 OpenMP 缩减的一般性问题,这个问题困扰了我一段时间。我的问题是关于将部分金额合并到归约中。它可以线性地完成,也可以作为线程数的对数完成。

假设我想减少一些功能double foo(int i)。有了 OpenMP,我就可以这样做。

double sum = 0.0;    
#pragma omp parallel for reduction (+:sum)
for(int i=0; i<n; i++) {
    sum += f(i);
}

但是,我声称以下代码同样有效。

double sum = 0.0;
#pragma omp parallel
{
    double sum_private = 0.0;
    #pragma omp for nowait
    for(int i=0; i<n; i++) {
        sum_private += f(i)
    }
    #pragma omp critical
    {
        sum += sum_private;
    }
}

不是,第二个代码案例实际上具有相同的性能,但它更通用。它可以处理我定义的任何运算符,而归约构造仅适用于普通旧数据类型的一些基本运算符。

我们假设有t线程。我之所以声称第二种方法同样快,是因为与并行循环相比,合并部分和的时间可以忽略不计。进行部分求和的时间与n/t合并总和的时间为t。所以只要n>>t或执行并行循环所需的时间(如果foo与求和相比很慢)足够大,合并可以忽略不计。

我听说可以将部分总和合并O(log(t))。然而,出于所有实际目的,我不认为这有什么帮助。 OpenMP 中的最大物理核心数量为 50 个,我们假设为 64 个。与并行循环相比,以 64 个步骤或 8 个二进制步骤合并 64 个值不会有太大区别。此外,合并某种二叉树中的值可能会产生比仅进行线性合并更大的开销,因此它甚至不一定更快。

什么时候将部分和合并到O(log(t))有帮助过吗?第一个代码案例何时比第二个代码案例具有性能优势?

我认识一些同事O(log(t))在带有 OpenCL 的 GPU 上(通过为每个二进制合并运行几次内核),但我还没有看到任何证据表明它比仅仅线性合并更好。

Edit:吉姆·考尼(Jim Cownie)希望看到实际测试而不是声称。下面是结果和代码。这是在具有四个物理内核的 Xeon E5-1620 (Sandy Bridge) 上通过 MSVC2012 64 位发布模式完成的。第一种情况和第二种情况都比不使用 OpenMP 时快大约 4.45 倍。

结果:

without OpenMP time 1.787158 s
first case     time 0.400462 s
second case    time 0.400456 s

代码:

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

double foo(int i) {
    double fi = i;
    return 1.0*fi/(1+fi*fi);
}

double reduce(int n) {
    double sum = 0.0f;
    for(int i=0; i<n; i++) {
        sum += foo(i);
    }
    return sum;
}

double reduce_omp(int n) {
    double sum = 0.0f;
    #pragma omp parallel for reduction(+:sum)
    for(int i=0; i<n; i++) {
        sum += foo(i);
    }
    return sum;
}

double reduce_omp2(int n) {
    double sum = 0.0f;
    #pragma omp parallel 
    {
        double sum_private = 0.0f;
        #pragma omp for nowait
        for(int i=0; i<n; i++) {
            sum_private += foo(i);
        }
        #pragma omp critical 
        {
            sum+= sum_private;
        }
    }
    return sum;
}

int main() {
    int n,r;
    double sum, dtime;
    n = 1<<28;
    r = 1;

    dtime = omp_get_wtime();
    for(int i=0; i<r; i++) sum = reduce(n);
    dtime = omp_get_wtime() - dtime;
    printf("time %f, sum %f\n", dtime, sum);

    reduce_omp(n);  //warm omp up

    dtime = omp_get_wtime();
    for(int i=0; i<r; i++) sum = reduce_omp(n);
    dtime = omp_get_wtime() - dtime;
    printf("time %f, sum %f\n", dtime, sum);

    dtime = omp_get_wtime();
    for(int i=0; i<r; i++) sum = reduce_omp2(n);
    dtime = omp_get_wtime() - dtime;
    printf("time %f, sum %f\n", dtime, sum);


}

OpenMP 实现将根据实现者对其运行的硬件的具体特征的了解来决定减少的最佳方法。在 CPU 数量较少的系统上,它可能会进行线性减少。在具有数百或数千个核心的系统(例如 GPU、Intel Phi)上,它可能会减少 log(n)。

对于非常大的问题,减少所花费的时间可能并不重要,但对于较小的问题,它可能会增加总运行时间的几个百分点。在许多情况下,您的实施可能同样快,但我怀疑它会更快,所以为什么不让 OpenMP 决定最佳缩减策略呢?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 OpenMP 进行缩减:线性合并或日志(线程数)合并 的相关文章

  • 在 Mac OS X 10.7.4 上使用 OpenCL 禁用 Nvidia 看门狗

    我有一个 OpenCL 程序 对于小问题运行良好 但是当运行较大的问题超过 Nvidia 硬件上运行内核的 8 10 秒时间限制时 虽然我没有将显示器连接到我正在计算的 GPU Nvidia GTX580 上 但一旦内核运行大约 8 10
  • 如何使用Python内置的map和reduce函数计算字符串中的字母频率

    我想使用Python的map和reduce内置函数来计算字符串中字母的频率 谁能提供一些关于我如何做到这一点的见解 到目前为止我所得到的 s the quick brown fox jumped over the lazy dog Map
  • HashSet 中的并行流不并行运行

    我有想要并行处理的元素集合 当我使用List 并行性有效 但是 当我使用Set 它不并行运行 我编写了一个代码示例来显示该问题 public static void main String args ParallelTest test ne
  • ElasticSearch 多滚动 Java API

    我想从索引中获取所有数据 由于项目数量对于内存来说太大 我使用滚动 很好的功能 client prepareSearch index setTypes myType setSearchType SearchType SCAN setScro
  • MPI Alltoallv 还是更好的单独发送和接收? (表现)

    我有许多进程 大约 100 到 1000 个 每个进程都必须将一些数据发送到其他一些进程 比如大约 10 个 通常 但并非总是必要 如果 A 发送到 B B 也会发送到 A 每个进程都知道它必须从哪个进程接收多少数据 所以我可以用MPI A
  • 如何在MPI中传递2D数组并使用C语言创建动态标签值?

    我是 MPI 编程新手 我有一个 8 x 10 数组 需要用它来并行查找每行的总和 在等级 0 进程 0 中 它将使用 2 维数组生成 8 x 10 矩阵 然后我会用tagnumber 作为数组的第一个索引值 行号 这样 我可以使用唯一的缓
  • 从 foreach 循环赋值

    我想并行化一个循环 例如 td lt data frame cbind c rep 1 4 2 rep 1 5 rep 1 10 2 names td lt c val id res lt rep NA NROW td for i in l
  • 我可以在 R 中并行读取 1 个大 CSV 文件吗? [复制]

    这个问题在这里已经有答案了 我有一个很大的 csv 文件 需要很长时间才能阅读 我可以使用 parallel 或相关的包在 R 中并行读取此内容吗 我尝试过使用 mclapply 但它不起作用 根据OP的评论 fread来自data tab
  • 如何在Python中使用多处理来加速循环执行

    我有两个清单 列表 A 包含 500 个单词 列表 B 包含 10000 个单词 我正在尝试为列表 A 找到与 B 相关的相似单词 我正在使用 Spacy 的相似函数 我面临的问题是计算需要很长时间 我是多处理使用的新手 因此请求帮助 如何
  • 处理异步并行任务的多个异常

    Problem 多个任务并行运行 所有任务 没有任务或其中任何任务都可能抛出异常 当所有任务完成后 必须报告所有可能发生的异常 通过日志 电子邮件 控制台输出 等等 预期行为 我可以通过 linq 使用异步 lambda 构建所有任务 然后
  • 调用许多网络服务的最佳方式?

    我有 30 家子公司 每家都实施了他们的 Web 服务 使用不同的技术 我需要实现一个Web服务来聚合它们 例如 所有子公司的Web服务都有一个名为的Web方法GetUserPoint int nationalCode 我需要实现我的网络服
  • 是否可以在 OpenCL 中并行运行求和计算?

    我是 OpenCL 的新手 不过 我了解 C C 基础知识和 OOP 我的问题如下 是否可以以某种方式并行运行求和计算任务 理论上可能吗 下面我将描述我尝试做的事情 任务例如是 double values new double 1000 l
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • 使用 TestNG 运行并行测试时捕获 WebDriver 屏幕截图

    我目前正在通过分别重写 TestListenerAdapter 方法 onTestFailure 和 onTestSuccess 来捕获 TestNG 中失败和成功的屏幕截图 为此 您需要指定要截取屏幕截图的驱动程序 我的问题 在方法级别并
  • 是否有一种类型安全的方法可以将较大的对象减少()为打字稿中的新类型?

    我有一个表示数据库查询结果的数据结构 它是一个具有许多属性的对象 所有属性都是标量 在我的例子中 都是字符串或数字 我想提取这些属性的一部分并填充一个具有已定义形状的新对象 const input Record
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

    我有以下使用 OpenMP 的 C C 代码 int nProcessors omp get max threads if argv 4 NULL printf argv 4 s n argv 4 nProcessors atoi argv
  • 多处理:仅使用物理核心?

    我有一个函数foo它消耗大量内存 我想并行运行多个实例 假设我有一个有 4 个物理核心的 CPU 每个核心有两个逻辑核心 我的系统有足够的内存来容纳 4 个实例foo并行但不是 8 个 此外 由于这 8 个核心中的 4 个是逻辑核心 我也不
  • 并行化斐波那契序列生成器

    我正在学习并行化 在一项练习中 我得到了一些我应该提高性能的算法 其中之一是斐波那契数列生成器 array 0 0 array 1 1 for q 2 q lt MAX q array q array q 1 array q 2 我怀疑 这
  • 与 GridSearchCV 的并行错误,与其他方法一起工作正常

    我使用 GridSearchCV 时遇到以下问题 它在使用时给我一个并行错误n jobs gt 1 同时n jobs gt 1与 RadonmForestClassifier 等单一模型配合良好 下面是一个显示错误的简单工作示例 train

随机推荐

  • 如何获取javax.comm API?

    我最近下载了一个项目SMS正在发送 但是当我尝试编译代码时 它给出了在线错误import javax comm 谁能告诉我在哪里可以找到javax comm以及放置在哪里 这样就不会出现编译错误 Oracle Java 通信 API 参考
  • 从一个枚举状态移动到下一个状态并循环

    我只有具有 3 种模式 ledOn ledBlink ledOFF 的枚举器 并且有一个可变模式来跟踪特定对象的模式 例如 我有一个 LED 以 ledOn 模式启动 我想在 5 秒后移动到下一个元素 即 ledBlink 然后移动到 le
  • Django self.cleaned_data Keyerror

    我正在编写一个 Django 网站 并且正在编写自己的表单验证 class CreateJobOpportunityForm forms Form subject forms CharField max length 30 start da
  • UIButton 中图像下的标签

    我正在尝试创建一个按钮 该按钮在图标下方有一些文本 有点像应用程序按钮 但它似乎很难实现 任何想法如何让文本显示below图像与UIButton 或者您可以只使用此类别 ObjC interface UIButton VerticalLay
  • 如何解决“react-native start”错误

    我刚刚安装了 node js 和 cli 安装了node js 安装了react native cli npm g react native cli 并创建了一个 新项目 react native init new project 在 ne
  • 使用 jQuery 将三个重复的 div 组合并为一个

    我这里还有另一个问题 我有几个重复的 div 组 一组有3个不同班级的分区 我需要做的是将其包装到一个 容器 中 当我使用wrapAll时 它会将所有内容包装到一个div中 这是我的 html div class bb box tl div
  • 使用jquery ajax将javascript对象转为php

    我有一个数组或一个 javascript 对象 我创建如下 arr arr length obj其中 obj 是一个经典的 JSON 字符串 例如 id 1 So arr似乎是一个 JavaScript 对象数组 我可以这样访问它 arr
  • 无法使用自定义适配器理解 NullPointerException

    我正在尝试创建一个列表视图 它作为可以显示 html 内容的 TextView WebView 和其他基本 TextView 我尝试扩展 SimpleAdapter 但我遇到了这个问题 如果有人能指出我正在做的错误 我会很高兴 在onCre
  • 从BackgroundWorker内的剪贴板获取数据

    我有一个后台工作者 在 DoWork 方法中我有以下内容 var clipboardData Application Current Dispatcher Invoke new Action gt Clipboard GetData Dat
  • 如何将操作栏选项卡向右对齐?

    我以编程方式添加了操作栏选项卡 我不知道如何将操作栏选项卡向右对齐 ActionBar bar getActionBar bar setNavigationMode ActionBar NAVIGATION MODE TABS instan
  • Google Apps 脚本中的 Cookie 处理 - 如何在标头中发送 Cookie?

    我正在尝试编写一个简单的脚本 从网页中获取文本并处理该字符串 但是 该网站要求我登录 我成功登录该网站 这是我登录的方式 var payload name1 val1 name2 val2 var opt payload payload m
  • 如何格式化 Winform 中 LostFocus 事件的所有文本框值

    我需要在失去焦点事件时向任何相关文本框值中每个数值的千位添加逗号 我创建了以下函数 public static void FormatNumerical this Control control if control is TextBox
  • 递归函数的复杂性 - 时间和空间

    我有兴趣知道如何计算递归函数的时间和空间复杂度 如排列 斐波那契 描述here 一般来说 我们可以在很多地方进行递归 而不仅仅是排列或递归 所以我正在寻找通常遵循的方法来计算时间和空间复杂度 谢谢 看一眼http www cs duke e
  • 带有 if 语句的函数中的全局变量

    好吧 我目前正在做一个用 python 制作二十一点游戏的项目 但遇到了一些麻烦 我的问题之一是我不知道何时将变量定义为全局变量 特别是在带有 if 语句的函数中 如果我在 if 语句之外有一个全局变量 我是否必须声明该变量在 if 语句内
  • 使用“import __main__”是个好习惯吗?

    我正在开发一个相对较大的 Python 应用程序 并且我希望将一些资源保留为可在多个不同模块中访问的全局变量 这些值包括版本号 版本日期 全局配置和一些资源的静态路径 我还包括了一个DEBUG由命令行选项设置的标志 以便我可以在调试模式下运
  • 需要有关流程的帮助

    当我开始像这样的过程时process Runtime getRuntime exec gnome terminal 它启动 shell 执行 我想停止 shell 执行并想从进程重定向 I O 有人能告诉我如何做到这一点吗 我的代码是 pu
  • 从 MFC 应用程序连接到 SQL Server Compact Edition (.sdf)

    我正在 Visual Studio 2008 中构建一个对纹理进行分类的 MFC 应用程序 我需要某种轻量级数据库来保存特征 只是一些双精度和字符串 这些特征可以是 在不同的计算机上携带该应用程序 能够从应用程序对其执行查询 搜索 更新 插
  • Cygwin 看到一个 Windows 看不到的文件——我想从 python 访问这个文件

    我有一个连接到 USB 的设备 它创建一个名为 Tpolling log 的日志文件 我可以通过 Cygwin 看到它 但通过 Windows 看不到它 隐藏文件设置为始终显示 我也无法从 python 访问它 我希望能够在 python
  • 在 GWT Web 应用程序中调用外部应用程序(即 Windows 计算器)

    当用户单击 GWT Web 应用程序中的按钮时 我尝试调用外部 Windows 应用程序 即 calc exe 有没有办法如何做到这一点 以下是我迄今为止已经尝试过的 1 尝试了 Runtime exec 和 ProcessBuilder
  • 使用 OpenMP 进行缩减:线性合并或日志(线程数)合并

    我有一个关于 OpenMP 缩减的一般性问题 这个问题困扰了我一段时间 我的问题是关于将部分金额合并到归约中 它可以线性地完成 也可以作为线程数的对数完成 假设我想减少一些功能double foo int i 有了 OpenMP 我就可以这