- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
给定 n
部分总和可以在 log2 并行步骤中对所有部分总和进行求和。例如,假设有八个线程和八个部分和:s0, s1, s2, s3, s4, s5, s6, s7
.这可以在 log2(8) = 3
中减少像这样的顺序步骤;
thread0 thread1 thread2 thread4
s0 += s1 s2 += s3 s4 += s5 s6 +=s7
s0 += s2 s4 += s6
s0 += s4
reduction
条款。我想出了一个解决方案,但我认为可以使用 OpenMP 的
task
找到更好的解决方案。条款。
a
.这是一些为每个线程并行填充私有(private)数组的代码。
int bins = 20;
int a[bins];
int **at; // array of pointers to arrays
for(int i = 0; i<bins; i++) a[i] = 0;
#pragma omp parallel
{
#pragma omp single
at = (int**)malloc(sizeof *at * omp_get_num_threads());
at[omp_get_thread_num()] = (int*)malloc(sizeof **at * bins);
int a_private[bins];
//arbitrary function to fill the arrays for each thread
for(int i = 0; i<bins; i++) at[omp_get_thread_num()][i] = i + omp_get_thread_num();
}
a
.这是我想出的解决方案。
#pragma omp parallel
{
int n = omp_get_num_threads();
for(int m=1; n>1; m*=2) {
int c = n%2;
n/=2;
#pragma omp for
for(int i = 0; i<n; i++) {
int *p1 = at[2*i*m], *p2 = at[2*i*m+m];
for(int j = 0; j<bins; j++) p1[j] += p2[j];
}
n+=c;
}
#pragma omp single
memcpy(a, at[0], sizeof *a*bins);
free(at[omp_get_thread_num()]);
#pragma omp single
free(at);
}
+=
运算符表示对数组求和。例如
s0 += s1
是
for(int i=0; i<bins; i++) s0[i] += s1[i]
n thread0 thread1 thread2 thread4
4 s0 += s1 s2 += s3 s4 += s5 s6 +=s7
2 s0 += s2 s4 += s6
1 s0 += s4
#pragma omp for
减持声明。但我不能使用
nowait
子句用这个方法来消除障碍。
task
可以找到更好的方法。条款。不幸的是,我对
task
几乎没有经验。条款和我迄今为止的所有努力都比我现在失败的减少更好。
task
条款?
#include <stdio.h>
#include <omp.h>
#include <stdlib.h>
#include <string.h>
void foo6() {
int nthreads = 13;
omp_set_num_threads(nthreads);
int bins= 21;
int a[bins];
int **at;
int m = 0;
int nsums = 0;
for(int i = 0; i<bins; i++) a[i] = 0;
#pragma omp parallel
{
int n = omp_get_num_threads();
int ithread = omp_get_thread_num();
#pragma omp single
at = (int**)malloc(sizeof *at * n * 2);
int* a_private = (int*)malloc(sizeof *a_private * bins);
//arbitrary fill function
for(int i = 0; i<bins; i++) a_private[i] = i + omp_get_thread_num();
#pragma omp critical (stack_section)
at[nsums++] = a_private;
while(nsums<2*n-2) {
int *p1, *p2;
char pop = 0;
#pragma omp critical (stack_section)
if((nsums-m)>1) p1 = at[m], p2 = at[m+1], m +=2, pop = 1;
if(pop) {
for(int i = 0; i<bins; i++) p1[i] += p2[i];
#pragma omp critical (stack_section)
at[nsums++] = p1;
}
}
#pragma omp barrier
#pragma omp single
memcpy(a, at[2*n-2], sizeof **at *bins);
free(a_private);
#pragma omp single
free(at);
}
for(int i = 0; i<bins; i++) printf("%d ", a[i]); puts("");
for(int i = 0; i<bins; i++) printf("%d ", (nthreads-1)*nthreads/2 +nthreads*i); puts("");
}
int main(void) {
foo6();
}
最佳答案
实际上,使用递归分而治之的方法通过任务干净利落地实现这一点非常简单。这差不多textbook代码。
void operation(int* p1, int* p2, size_t bins)
{
for (int i = 0; i < bins; i++)
p1[i] += p2[i];
}
void reduce(int** arrs, size_t bins, int begin, int end)
{
assert(begin < end);
if (end - begin == 1) {
return;
}
int pivot = (begin + end) / 2;
/* Moving the termination condition here will avoid very short tasks,
* but make the code less nice. */
#pragma omp task
reduce(arrs, bins, begin, pivot);
#pragma omp task
reduce(arrs, bins, pivot, end);
#pragma omp taskwait
/* now begin and pivot contain the partial sums. */
operation(arrs[begin], arrs[pivot], bins);
}
/* call this within a parallel region */
#pragma omp single
reduce(at, bins, 0, n);
bins=10000
所以减少实际上需要一点时间。在没有涡轮增压的 24 核 Haswell 系统上执行。 gcc 4.8.4,
-O3
.我在实际执行周围添加了一些缓冲区以隐藏初始化/后处理
omp for
循环 omp critical
一种任务。 omp task
critical
解决方案有一些有趣的方面,被动线程不会持续等待,因此它们更有可能消耗 CPU 资源。这可能对性能不利,例如在涡轮模式的情况下。
task
通过避免立即返回的生成任务,解决方案具有更大的优化潜力。这些解决方案的性能还很大程度上取决于特定的 OpenMP 运行时。英特尔的运行时似乎对任务的处理要差得多。
proccess_data_v1
的时间表来自
this question .
at
获取数据。循环内的数组,没有副本。我确实用
NULL
初始化了工作数组并在第一次简单地移动指针:
void meta_op(int** pp1, int* p2, size_t bins)
{
if (*pp1 == NULL) {
*pp1 = p2;
return;
}
operation(*pp1, p2, bins);
}
// ...
// declare before parallel region as global
int* awork = NULL;
#pragma omp declare reduction(merge : int* : meta_op(&omp_out, omp_in, 100000)) initializer (omp_priv=NULL)
#pragma omp for reduction(merge : awork)
for (int t = 0; t < n; t++) {
meta_op(&awork, at[t], bins);
}
icc 16.0.2
, 底部是
gcc 5.3.0
, 都与
-O3
.
gcc
/
libgomp
,但对我来说发生的事情并不是很明显。从中间代码/反汇编来看,他们似乎将最终合并包装在
GOMP_atomic_start
中。/
end
- 这似乎是一个全局互斥锁。同样
icc
将调用包装到
operation
在
kmpc_critical
.我想在昂贵的自定义减少操作中没有太多优化。传统的减少可以通过硬件支持的原子操作来完成。
operation
速度更快,因为输入在本地缓存,但由于序列化,它总体上更慢。同样,由于差异很大,这不是一个完美的比较,并且早期的屏幕截图具有不同的
gcc
版本。但是趋势很明显,我也有缓存效果的数据。
关于c - 对数时间并行减少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35675466/
您好,我是使用 xampp 的 PHPmyadmin 新手,没有 MYSQL 背景。当我喜欢研究它是如何工作的时,我的脑海中浮现出一个想法,它让我一周都无法休眠,因为我似乎无法弄清楚如何使用 MIN(
Go docs say (强调): Programs using times should typically store and pass them as values, not pointers.
我有一组用户在 8 月 1 日有一个条目。我想找到在 8 月 1 日有条目但在 8 月 2 日没有做任何事情的用户。 现在是 10 月,所以事件已经过去很久了。 我有限的知识说: SELECT * F
我有以下代码,主要编码和取消编码时间结构。这是代码 package main import ( "fmt" "time" "encoding/json" ) type chec
您能详细解释一下“用户 CPU 时间”和“系统 CPU 时间”吗?我读了很多,但我不太理解。 最佳答案 区别在于时间花在用户空间还是内核空间。用户 CPU 时间是处理器运行程序代码(或库中的代码)所花
应用程序不计算东西,但做输入/输出、读取文件、使用网络。我希望探查器显示它。 我希望像 callgrind 中的东西一样,在每个问题中调用 clock_gettime。 或者像 oprofile 那样
目前我的 web 应用程序接收 websocket 数据来触发操作。 这会在页面重新加载时中断,因此我需要一个能够触发特定事件的客户端解决方案。 这个想法可行吗? 假设你有 TimeX = curre
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我有一个 Instant (org.joda.time.Instant) 的实例,我在一些 api 响应中得到它。我有另一个来自 (java.time.Instant) 的实例,这是我从其他调用中获得
如何集成功能 f(y) w.r.t 时间;即 'y'是一个包含 3000 个值和值 time(t) 的数组从 1 到 3000 不等。所以,在整合 f(y) 后我需要 3000 个值. 积分将是不确定
可以通过 CLI 创建命名空间,但是如何使用 Java SDK 来创建命名空间? 最佳答案 它以编程方式通过 gRPC API 完成由服务公开。 在 Java 中,生成的 gRPC 客户端可以通过 W
我有一个函数,它接受 2 组日期(开始日期和结束日期),这些日期将用于我的匹配引擎 我必须知道start_date1和end_date1是否在start_date2和end_date2内 快进:当我在
我想从 Python 脚本运行“time”unix 命令,以计算非 Python 应用程序的执行时间。我会使用 os.system 方法。有什么方法可以在Python中保存这个输出吗?我的目标是多次运
我正在寻找一种“漂亮的数字”算法来确定日期/时间值轴上的标签。我熟悉 Paul Heckbert's Nice Numbers algorithm . 我有一个在 X 轴上显示时间/日期的图,用户可以
在 PowerShell 中,您可以格式化日期以返回当前小时,如下所示: Get-Date -UFormat %H 您可以像这样在 UTC 中获取日期字符串: $dateNow = Get-Date
我正在尝试使用 Javascript 向父子窗口添加一些页面加载检查功能。 我的目标是“从父窗口”检测,每次子窗口完全加载然后执行一些代码。 我在父窗口中使用以下代码示例: childPage=wi
我正在尝试设置此 FFmpeg 命令的 drawtext 何时开始,我尝试使用 start_number 但看起来它不会成功。 ffmpeg -i 1.mp4 -acodec aac -keyint_
我收到了一个 Excel (2010) 电子表格,它基本上是一个文本转储。 单元格 - J8 具有以下信息 2014 年 2 月 4 日星期二 00:08:06 EST 单元格 - L8 具有以下信息
我收到的原始数据包含一列具有以下日期和时间戳格式的数据: 2014 年 3 月 31 日凌晨 3:38 单元格的格式并不一致,因为有些单元格有单个空格,而另一些单元格中有两个或三个字符之间的空格。所以
我想知道是否有办法在我的 Grails 应用程序顶部显示版本和构建日期。 编辑:我应该说我正在寻找构建应用程序的日期/时间。 最佳答案 在您的主模板中,或任何地方。 Server version:
我是一名优秀的程序员,十分优秀!