- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经使用 OpenMP 在 C++ 中实现了总面积表(或积分图像)。
问题是顺序代码总是比并行代码快,即使改变线程数和图像大小也是如此。
例如,我尝试了从 (100x100) 到 (10000x10000) 的图像和从 1 到 64 的线程,但没有一个组合是更快的。
我也在不同的机器上试过这段代码,比如:
已使用 OpenMP 函数测量时间:omp_get_wtime()
。
对于编译,我使用:g++ -fopenmp -Wall main.cpp
。
并行代码如下:
void transpose(unsigned long *src, unsigned long *dst, const int N, const int M) {
#pragma omp parallel for
for(int n = 0; n<N*M; n++) {
int i = n/N;
int j = n%N;
dst[n] = src[M*j + i];
}
}
unsigned long * integralImageMP(uint8_t*x, int n, int m){
unsigned long * out = new unsigned long[n*m];
unsigned long * rows = new unsigned long[n*m];
#pragma omp parallel for
for (int i = 0; i < n; ++i)
{
rows[i*m] = x[i*m];
for (int j = 1; j < m; ++j)
{
rows[i*m + j] = x[i*m + j] + rows[i*m + j - 1];
}
}
transpose(rows, out, n, m);
#pragma omp parallel for
for (int i = 0; i < n; ++i)
{
rows[i*m] = out[i*m];
for (int j = 1; j < m; ++j)
{
rows[i*m + j] = out[i*m + j] + rows[i*m + j - 1];
}
}
transpose(rows, out, m, n);
delete [] rows;
return out;
}
这是顺序代码:
unsigned long * integralImage(uint8_t*x, int n, int m){
unsigned long * out = new unsigned long[n*m];
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
unsigned long val = x[i*m + j];
if (i>=1)
{
val += out[(i-1)*m + j];
if (j>=1)
{
val += out[i*m + j - 1] - out[(i-1)*m + j - 1];
}
} else {
if (j>=1)
{
val += out[i*m + j -1];
}
}
out[i*m + j] = val;
}
}
return out;
}
我也尝试过不使用 transpose
但它更慢可能是因为缓存访问。
调用代码示例:
int main(int argc, char **argv){
uint8_t* image = //read image from file (gray scale)
int height = //height of the image
int width = //width of the image
double start_omp = omp_get_wtime();
unsigned long* integral_image_parallel = integralImageMP(image, height, width); //parallel
double end_omp = omp_get_wtime();
double time_tot = end_omp - start_omp;
std::cout << time_tot << std::endl;
start_omp = omp_get_wtime();
unsigned long* integral_image_serial = integralImage(image, height, width); //sequential
end_omp = omp_get_wtime();
time_tot = end_omp - start_omp;
std::cout << time_tot << std::endl;
return 0;
}
每个线程都在处理一个行 block (也许每个线程正在做的事情的说明会很有用): 其中 ColumnSum 完成转置矩阵并重复 RowSum。
最佳答案
首先让我说,结果让我有点惊讶,我猜测问题出在转置算法所需的非本地内存访问中。
无论如何,您都可以通过两遍方法将顺序算法转换为并行算法来缓解它。第一遍必须在相隔 N 行的 T 个线程中计算二维积分,第二遍必须补偿每个 block 不是从前一行的累积结果而是从零开始的事实。
使用 Matlab 的示例以 2D 形式显示了原理。
f=fix(rand(12,8)*8) % A random matrix with 12 rows, 8 columns
5 6 1 4 7 5 4 4
4 6 0 7 1 3 2 0
7 0 2 3 0 1 6 3
5 3 1 7 4 3 7 2
6 4 3 2 7 3 5 1
3 3 2 5 5 0 2 1
3 5 7 5 1 4 4 3
6 5 7 4 2 1 0 0
0 2 0 5 3 3 7 4
1 3 5 5 7 4 7 3
1 0 2 1 1 2 6 5
3 7 3 1 6 2 2 5
ff=cumsum(cumsum(f')') % The Summed Area Table
5 11 12 16 23 28 32 36
9 21 22 33 41 49 55 59
16 28 31 45 53 62 74 81
21 36 40 61 73 85 104 113
27 46 53 76 95 110 134 144
30 52 61 89 113 128 154 165
33 60 76 109 134 153 183 197
39 71 94 131 158 178 208 222
39 73 96 138 168 191 228 246
40 77 105 152 189 216 260 281
41 78 108 156 194 223 273 299
44 88 121 170 214 245 297 328
fx=[cumsum(cumsum(f(1:4,:)')'); % The original table summed in
cumsum(cumsum(f(5:8,:)')'); % three parts -- 4 rows per each
cumsum(cumsum(f(9:12,:)')')] % "thread"
5 11 12 16 23 28 32 36
9 21 22 33 41 49 55 59
16 28 31 45 53 62 74 81
21 36 40 61 73 85 104 113 %% Notice this row #4
6 10 13 15 22 25 30 31
9 16 21 28 40 43 50 52
12 24 36 48 61 68 79 84
18 35 54 70 85 93 104 109 %% Notice this row #8
0 2 2 7 10 13 20 24
1 6 11 21 31 38 52 59
2 7 14 25 36 45 65 77
5 17 27 39 56 67 89 106
fx(4,:) + fx(8,:) %% this is the SUM of row #4 and row #8
39 71 94 131 158 178 208 222
%% and finally -- what is the difference of the piecewise
%% calculated result and the real result?
ff-fx
0 0 0 0 0 0 0 0 %% look !! the first block
0 0 0 0 0 0 0 0 %% is already correct
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
21 36 40 61 73 85 104 113 %% All these rows in this
21 36 40 61 73 85 104 113 %% block are short by
21 36 40 61 73 85 104 113 %% the row #4 above
21 36 40 61 73 85 104 113 %%
39 71 94 131 158 178 208 222 %% and all these rows
39 71 94 131 158 178 208 222 %% in this block are short
39 71 94 131 158 178 208 222 %% by the SUM of the rows
39 71 94 131 158 178 208 222 %% #4 and #8 above
幸运的是,可以开始整合 block 2,即在 block #1 得到补偿之前的第 2N..3N-1 行 - 只需计算偏移量,这是一个相对较小的顺序 任务。
acc_for_block_2 = row[2*N-1] + row[N-1];
acc_for_block_3 = acc_for_block_2 + row[3*N-1];
..
acc_for_block_T-1 = acc_for_block_(T-2) + row[N*(T-1)-1];
关于c++ - OpenMP 积分图像比顺序图像慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50352166/
请提出一个数据结构来表示内存中的记录列表。每条记录由以下部分组成: 用户名 积分 排名(基于积分)- 可选字段- 可以存储在记录中或可以动态计算 数据结构应该支持高效实现以下操作: Insert(re
我正在使用 integrate 将一些集成到循环中我想出了一个我无法理解的错误,也无法摆脱。这是我可以提取的 MWE: u_min = 0.06911363 u_max = 1.011011 m =
掌上生活17要吃节签到抽腾讯视频爱奇艺会员月卡 5元饭票 积分 打开掌上生活APP,首页全部专区进入找到活动日历往下拉可以看到17要吃节进入活动页面 可以集3个赞兑换星巴克喝,也可以签到抽爱
我遇到了一个有趣但相当烦人的问题。 我正在尝试集成一个从数据集计算出来的函数。 数据可以在这里找到:Link to sample.txt . 我首先将一条线拟合到我的数据中。这可以通过 approxf
当我使用 Three.js 创建一个点时,它看起来像一个正方形。我怎样才能使它看起来圆?我在文档中看到了一些混合因素,但我不太明白如何在我的观点中使用它们,我什至不知道这是否是正确的方法。 最佳答案
我尝试了此处找到的示例代码: https://developers.facebook.com/docs/creditsapi/即使我添加了我的公司地址和付款方式,我仍然会收到此错误: API Erro
我想使用 scipy.integrate.ode 求解器。我只能将可调用函数 f 定义为离散点数组(因为它取决于先前迭代的积分结果)。但是从文档来看,集成商似乎希望可调用函数是一个连续函数。我想需要进
我无法理解 sympy.integrate() 函数的行为。最简单的例子,整合和分化: t = sy.Symbol('t') t1 = sy.Symbol('t1') f = sy.Function(
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我在 zeroSSL 面板中有一个过期的 SSL 证书,但我无法更新它,因为我生成了 3/3 证书。 1 仍处于事件状态,但其他两个已过期(已为这些相同的域提前生成)。是否有可能以某种方式删除其中一个
我有一个数据结构,例如表达式树或图形。我想添加一些“测量”功能,例如depth和 size . 如何最好地键入这些函数? 我认为以下三个变体的用处大致相同: depth :: Expr -> Int
让 Mathematica 7 或 8 进行积分的最佳方法是什么 NIntegrate[Exp[-x]/Sin[Pi x], {x, 0, 50}] 每个整数都有极点 - 我们需要柯西原理值。这个想法
只是想知道是否有人知道如何查询 Facebook Credits (FBC) API 以获取用户拥有的信用数?我的应用程序有此要求,并且 FBC API 中没有对此进行解释或提及。 谢谢 最佳答案 也
好的,所以这让我难住了超过 3 天,在离解决方案还差一步之后,我要在这里试试运气。 过去,我为一个特定的排序数据集编写了一些代码,它是这样的: n maxobs){FG = 1} else {
在激活通过 MSDN 订阅获得的 Azure 积分时,我使用了工作帐户。 事实证明,由于我没有 Active Directory 管理员权限,因此无法注册应用程序等。这使得它毫无用处。我也不太可能获得
如何使用 Romberg 积分近似计算以下积分, min:1, max:1.6, integral (2x)/((x^2)-4) 还计算 Romberg 表,直到 |R_n-1,n-1 - R_n,n
我正在尝试计算积分 sin(x)/x , x = [0,inf] 我做了以下事情: import math from scipy.integrate import quad t = float("in
所以我的代码有效,只是出于某种原因,我的代码总是运行两个 if 语句(两个 y 方程,无论我为第一个 fprintf 问题输入哪个数字)。此外,t,y 列总是比 t,y2 列长得多(编辑,即如果我输入
我有一个简单的问题。我正在尝试使用 Matlab R2012a 评估 0 阶贝塞尔函数的不正确积分: v = integral(@(x)(besselj(0, x), 0, Inf) 这给了我 v =
我正在与 iPhone Native Game App 一起开发 Facebook Canvas Game 项目,该项目使用 Facebook 积分作为唯一的虚拟货币。 据我们所知,Apple 应用内
我是一名优秀的程序员,十分优秀!