- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在 Intel CPU 和 NVIDIA GPU 上运行相同的 OpenCL 内核代码,前者的结果是错误的,后者是正确的;奇怪的是,如果我做了一些看似不相关的更改,那么在这两种情况下输出都会按预期工作。
该函数的目标是计算 A(三角形)和 B(正则)之间的矩阵乘法,其中 A 在运算中的位置由变量 left
的值确定。该错误仅在 left
为真且 for 循环至少迭代两次时出现。
为了清楚起见,这里省略了一些不应该影响的代码片段。
__kernel void blas_strmm(int left, int upper, int nota, int unit, int row, int dim, int m, int n,
float alpha, __global const float *a, __global const float *b, __global float *c) {
/* [...] */
int ty = get_local_id(1);
int y = ty + BLOCK_SIZE * get_group_id(1);
int by = y;
__local float Bs[BLOCK_SIZE][BLOCK_SIZE];
/* [...] */
for(int i=start; i<end; i+=BLOCK_SIZE) {
if(left) {
ay = i+ty;
bx = i+tx;
}
else {
ax = i+tx;
by = i+ty;
}
barrier(CLK_LOCAL_MEM_FENCE);
/* [...] (Load As) */
if(bx >= m || by >= n)
Bs[tx][ty] = 0;
else
Bs[tx][ty] = b[bx*n+by];
barrier(CLK_LOCAL_MEM_FENCE);
/* [...] (Calculate Csub) */
}
if(y < n && x < (left ? row : m)) // In bounds
c[x*n+y] = alpha*Csub;
}
现在变得奇怪了。
如您所见,如果 left
为真,则 by
始终等于 y
。我检查了(使用一些 printf
,请注意)并且 left
始终为真,并且永远不会执行循环内 else 分支上的代码。尽管如此,如果我删除或注释掉那里的 by = i+ty
行,代码就可以工作。为什么?我还不知道,但我认为这可能与 by
没有分配预期值有关。
我的思路让我检查 by
和 y
之间是否存在差异,因为它们应该始终具有相同的值;我添加了一行来检查 by != y
但该比较总是返回 false,如预期的那样。所以我继续为 y
更改了 by
的外观,所以行
if(bx >= m || by >= n)
转化为
if(bx >= m || y >= n)
它又开始工作了,尽管我还在下面三行中正确地使用了变量 by
。
怀着开放的心态,我尝试了一些其他的东西,我得出的结论是,如果我在循环中添加以下行,代码就可以工作,只要它位于初始 if/else 之后和if 我刚才提到的条件。
if(y >= n) left = 1;
里面的代码 (left = 1
) 可以替换任何东西(printf
,另一个无用赋值,等等),但是条件有点限制。以下是一些使代码输出正确值的示例:
if(y >= n) left = 1;
if(y < n) left = 1;
if(y+1 < n+1) left = 1;
if(n > y) left = 1;
还有一些不起作用,请注意我正在测试的特定示例中的 m = n
:
if(y >= n+1) left = 1;
if(y > n) left = 1;
if(y >= m) left = 1;
/* etc. */
这就是我现在的处境。我添加了一行,它根本不应该影响程序,但它可以正常工作。这个神奇的解决方案并不令我满意,我想知道我的 CPU 内部发生了什么以及为什么。
为了确保我没有忘记任何东西,这里是 full function code和一个 gist with example inputs and outputs .
非常感谢。
用户 DarkZeros 和 sharpneli 的假设都是正确的:for 循环内的障碍没有被击中正确的次数。特别是,有一个错误涉及每个本地组的第一个元素,这使得它运行的迭代比其余的少,从而引发未定义的行为。事后看来,这是显而易见的痛苦。
感谢大家的回答和时间。
最佳答案
您是否检查过 get_local_size 总是返回正确的值?
您说“简而言之,矩阵的全长被划分为 BLOCK_SIZE 的局部 block 并并行运行;”。请记住,OpenCL 只允许工作组内的任何并发。因此,如果您调用全局大小为 [32,32] 且局部大小为 [16,16] 的 enqueueNDrange,则第一个线程 block 可能从头到尾运行,然后是第二个,然后是第三个等等。您无法在两者之间同步工作组。
您的 EnqueueNDRange 调用是什么?非常感谢获得示例输出所需的调用示例(主要对全局和局部大小参数感兴趣)。
(我会在评论中提出这个问题,但我是新用户)。
E(有答案,经验证没有,还需要更多信息): http://multicore.doc.ic.ac.uk/tools/GPUVerify/
通过使用它,我得到了一个提示,即不一致的控制流可能会达到障碍。
这完全取决于 dim、nota 和 upper get 的值。你能提供一些例子吗?
我做了一些测试。假设 left = 1.nota != upper 和 dim = 32,行为 16 或 32 或诸如此类,仍然有效并得到以下结果:
...
gid0: 2 gid1: 0 lid0: 14 lid1: 13 start: 0 end: 32
gid0: 2 gid1: 0 lid0: 14 lid1: 14 start: 0 end: 32
gid0: 2 gid1: 0 lid0: 14 lid1: 15 start: 0 end: 32
gid0: 2 gid1: 0 lid0: 15 lid1: 0 start: 0 end: 48
gid0: 2 gid1: 0 lid0: 15 lid1: 1 start: 0 end: 48
gid0: 2 gid1: 0 lid0: 15 lid1: 2 start: 0 end: 48
...
因此,如果我对变量值的假设甚至接近于正确,那么你就会遇到障碍分歧问题。一些线程遇到了另一个线程永远不会遇到的障碍。我很惊讶它没有死锁。
关于c - 我的 OpenCL 代码基于一个看似 noop 更改输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19766922/
我在将两个“相同”字符串转换为大写时遇到了一个非常奇怪的问题。该程序正在从网站读取行并将其与存储在文本文件中的行进行比较。如果未找到该行,则将其添加到文件末尾。除非该行包含特殊字符,否则这非常有效。由
我见过对象创建的各种模式,但在深入研究 Firefox 框架 Javascript 后,我注意到他们使用的是我以前从未见过的约定,我希望这里有人可以确认我的假设或纠正我: 在构建类时,我过去曾这样
多亏了我在 Oxfam 书店找到的一本小书和一本大书,我一直在研究 C、C++ 和 Allegro。我现在理解得很好,但我遇到了困难……每当我编译时,我都会遇到这些错误: archiboldian@a
也许标题可以改写得稍微好一点,但基本上我想知道 facebook 之类的公司如何实现关于新通知/消息等的“实时”界面。我知道这样一个社交网络背后的复杂性太在这个小的 SO 线程中有很多讨论,但如果有人
我想使用 R 的 C 接口(interface)编写一个 R 函数,该函数采用 2 列递增的非重叠整数间隔矩阵,并返回一个包含这些间隔加上一些附加间隔的列表,这样就没有间隙。例如,它应该取矩阵 rbi
我们的崩溃日志系统显示崩溃,我不明白它是如何发生的。用户输入未知。我已添加日志记录,但结果只有在下一个版本(约 2 周)后才能看到。 下面的代码如何抛出下一个异常: Crashes with java
我正在java1.7下使用JavaFX进行编程,除了这部分之外,所有内容都适用于我的代码。问题是,只有最终结果被写出来。当程序运行时,我希望它在标签中显示“Ping 测试正在运行”文本。但它不会这样做
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我有一个作用域枚举: enum class E { A, B, C }; 现在我想要一个函数,它接受该作用域 int 的值或 int 本身。 应该是这样的: template ::value, int
我有以下 Python 脚本: x = 300000000.0 while (x < x + x): x = x + x print "exec: " + str(x) print "
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: how does do{} while(0) work in macro? 示例来自 this博文: #de
我的问题是:“语言设计者为什么要考虑允许在不同数据类型之间进行比较?”。另外,这在功能语言中是否更有意义? 例如,在erlang中,可以执行以下比较: %% Tuples are greater th
我在玩 GHCI,遇到了这个(对我来说)奇怪的小东西。 我试过这个: λ> let fibs = 1 : 1 : zipWith (+) fibs (tail fibs) λ> fibs 只是为了看看
我们正在 Fixtures 的帮助下为我们的 Grails 2.0.0 应用程序编写集成测试。和 Buid-Test-Data插件。 在测试过程中,发现集成测试有时会失败,有时会通过。运行“test-
我目前有一个脚本应该获取并返回 Bit.ly 链接的点击次数。我首先从 Bitly url 收集和读取数据,我似乎在做正确的事情。 bitly_data = "https://api-ssl.
我正在为我的老师测试一些东西,他想看看如果我们模拟同步,下面的程序如何运行得更快(我知道它不可能完全同步,这只是为了实验学习/练习)多只 turtle 的运动。我尝试过使用诸如多处理、线程之类的模块,
所以我在一个输出大图像(从 30MB 到 2GB+ 的任何地方)的设备上工作。在我们开始创建这些图像之一之前,我们通过 GetDiskFreeSpaceEx 检查是否有足够的磁盘空间。通常(在这种情况
我正在尝试通过深入了解操作系统的底层细节来学习操作系统。我现在上的类(class)是MIT 6.828 Operating System Engineering 。该实验室要求学生追踪 BIOS 以获
我知道你不能在 Lua 中重复匹配组。例如,如果我想匹配两个连续的 "45",我不能这样做: print(string.find("some 4545 text", "(%d%d)+")) 这将打印
这是我创建的一个 plunker:http://plnkr.co/edit/ZoKsO7wu5OvCYtwEi9Iy?p=preview . 点击列表中使用 ng-repeat 渲染的项目之一,例如
我是一名优秀的程序员,十分优秀!