并行化嵌套的for循环:分解数据

如何解决并行化嵌套的for循环:分解数据

我有两个带有整数参数的函数;称为 f g 。我还有另一个函数 h ,它带有两个整数参数。给定一个大小为D的正方形U(意思是:{m0,m0 + 1,..,m0 + D-1} x {n0,n0 + 1,...,n0 + D-1}),我有一个过程给定包含数组f(m0),f(m0 + 1)的数组farrgarr,用于计算D上的f(n)g(m)h(n,m)的时间大致线性),...,f(m0 + D-1)和g(n0),g(n0 + 1),...,g(n0 + D-1);让我们将该程序视为一个黑盒,通过调用Sum(farr,garr,m0,n0,D)来调用它。我们可以计算出farr [0] = f(m0),... farr [D-1] = f(m0 + D-1)或garr [0] = garr(n0),garr [1] = g(n0通过调用Fillf(f,m0,D)和Fillg(g,m0,D)+1),...,garr [n0 + D-1]在时间上大致线性于D。

问题是如何有效计算{0,1,...,rD-1} x {中的所有(n,m)的f(n)g(m)h(n,m)的总和0,1,...,rD-1}(说)并行。摘要很简单-我想知道的是如何在OpenMP中进行。

最简单的方法可能是这样的:

S=0;
#pragma omp parallel for collapse(2) schedule(dynamic) private(m0,n0,farr,garr) reduction(+:S)
for(m0=0; m0<r*D; m0+=D)
 for(n0=0; n0<r*D; n0+=D)
  farr = (short *) calloc(D,sizeof(int));
  Fillf(farr,m0,D);
  garr = (short *) calloc(D,sizeof(int));
  Fillg(garr,D);
  S+=Sum(farr,garr,D)
  free(garr);
  free(farr);

这已经足够好了,但是它的缺点是farrgarr的每个段都被计算了r次而不是一次。考虑到整体的计算复杂度没有改变(不会比O(r ^ 2 D)好),这几乎不是一个悲剧,但是仍然是不可取的。

另一种方法是写

S=0;
#pragma omp parallel for schedule(dynamic) private(m0,garr) reduction(+:S)
for(m0=0; m0<r*D; m0+=D) {
 farr = (short *) calloc(D,sizeof(int));
 Fillf(farr,D);
 for(n0=0; n0<r*D; n0+=D) {
  garr = (short *) calloc(D,D)
  free(garr);
 }
 free(farr);
}
  

这也是一个可行的解决方案,但是:(a)garr的每个段仍获得r次而不是一次的计算,(b)如果可用线程数比{ {1}}(但小于r)。在这里我们不能使用r^2,因为两个循环之间正在发生某些事情。

显然应该可以做得更好。使用OpenMP编写或多或少显而易见的过程的直接方法是什么? (应该将collapse(2)farr的一个预先计算的分段的大小约为sqrt(s)D,其中s是可用线程的数量,然后对{{ 1}}和garr遍历大约D个sqrt的长度?)

解决方法

如果要避免对ComboBoxfarr进行重复计算,则至少有两个选择:

  1. 预先在一个单独的循环中计算并存储所有garr,并采取与第二种选择相同的方法。 (可选)也可以预先计算和存储所有garr

  2. 修改第二种选择以并行化内部循环而不是外部循环。这也将使您能够从循环中提升farr的分配和取消分配:

    farr

请注意

  • 如果S = 0; farr = malloc(D,sizeof(int)); for (int m0 = 0; m0 < r * D; m0 += D) { int S2 = 0; Fillf(farr,m0,D); #pragma omp parallel for private(farr,m0) reduction(+:S2) for (int n0 = 0; n0 < r * D; n0 += D) { int *garr = calloc(D,sizeof(int)); Fillg(garr,n0,D); S2 += Sum(farr,garr,D) free(garr); } S += S2; } free(farr); 假设其数组参数最初是零填充的(如Fillf()确保),那么从循环中提升内存分配将需要在每次调用之前手动进行零填充,但这仍然比重新分配和重新分配便宜。
  • 我删除了调度子句,因为看来动态调度不会对这种计算有任何好处
  • calloc()声明为私有,只会使指针成为私有,而不是指针指向的数据。而且,由于farrfarr都没有在并行循环中被修改,因此将它们声明为私有实际上并没有用。我将示例代码中的m0子句留在了这里,主要是作为这些说明的重点。
  • 重新计算private的各种值所节省的费用与更细粒度的并行性带来的额外开销相抵触。如果内部循环的每次迭代的工作仍然相对较大,那么这更可能是一个胜利。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-