3

将存储在主机内存中的 2d 图像传输到 OpenCL 时,它如何读取值 - 主要行还是主要列?让我们假设行专业。

index = row*NUM_COLS + col

存储在主机内存中的 3d 图像怎么样?我相信这被视为一堆 2D 图像(假设是行主要的)。然后像素 (row,col,slice) 在 OpenCL 方面的限制 (NUM_ROWS,NUM_COLS,NUM_SLICES) 位于:

index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col

但是,根据维基百科公式,3d Row Major 索引应该是:

index = slice + NUM_SLICES*(col + NUM_COLS*row) 
      = row*NUM_COLS*NUM_SLICES + col*NUM_SLICES + slices

根据同一篇文章 Column Major Ordering 访问应该是:

index = row + NUM_ROWS*(col + NUM_COLS*slice)
      = slice*NUM_ROWS*NUM_COLS + col*NUM_ROWS + row

这些似乎都与 OpenCL 在 3d 案例中所做的相匹配。

所以我想我真的有两个问题

  1. 如何布局内存以将 2d 和 3d 图像传输到 OpenCL?
  2. 为什么看起来 OpenCL 在 3d 案例中选择了非标准的内存布局?

编辑

我将维基百科文章视为通用布局方案。“行”或“列”是辅助标签词。无论您是处理限制为 (NUM_ROWS, NUM_COLS, NUM_SLICES) 还是 (x,y,z) (WIDTH, HEIGHT, DEPTH) 的元组 (row, col, slice) 都无关紧要,只要它是一致的。它只是告诉你哪个维度在内存中是连续的。在“主要行”中,它是最后一个维度 - z 值彼此相邻,在主要列中,它是第一个维度 - x。

所以我再一次认为 x,y,z 3d 图像索引的“主要行”布局应该是:

index = z + DEPTH * (y + HEIGHT * x) = x * HEIGHT * DEPTH + y * HEIGHT + z

它不是。但是,我想你可以选择任何你想要的方案。

4

1 回答 1

3

首先,您对 OpenCL 布局的假设是正确的。OpenCL 确实使用了您描述的布局,并且您为 2D 和 3D 情况提供的公式是正确的,组件接组件,像素接像素,行接续行,切片接续切片。我(有 OpenGL 背景)认为这是一个非常标准的。

然而,这里有一点命名混乱,因为行主要意思是维基百科所说的,第一个维度以最低频率变化,最后一个维度是连续的。然而对于图像,行实际上不是第一个维度,而是y维度,列是x。因此,虽然 OpenCL(至少在 2D 中)使用文字“行主要”布局(因为行更改较少),但通常认为(在Wikipedia使用的术语中)而不是列主要,因为第一个维度(x)是连续的。这可以很好地转换为 3D,其中最后一个维度 ( z) 以最低频率变化。所以你把维基百科弄错了,它实际上是说一般的列专业(扩展到 3D)是

index = z*WIDTH*HEIGHT + y*WIDTH + x

其中,鉴于x=coly=row,确实是

index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col

这正是 OpenCL 使用的。因此,要回答您的实际问题:

  1. 就像您在问题的第一部分中解释的那样。

  2. 因为您将 Wikipedia 弄错了,并且将基于矩阵的(row,col)索引与基于图像的索引混淆(x,y)了,而 OpenCL 使用的内容对应于Wikipedia通常所说的 column-major。

编辑:基于索引的寻址(如矩阵)和基于坐标的寻址(如图像)的这种混淆是混淆的常见来源。例如,在 OpenCV(一个著名的图像处理库)中,图像被表示和寻址为矩阵,因此类似于(row,col),这对于实际图像意味着(y,x).

于 2013-07-17T16:42:09.860 回答