我正在尝试调试我在CUDA计算机上的索引问题
Cuda Machine Info:
{1-> {Name-> Tesla C2050,Clock Rate-> 1147000,Compute Capabilities-> 2.,GPU Overlap-> 1,Maximum Block Dimensions - > {1024,1024,64 },最大网格尺寸 - > {65535,65535,65535},每块最大线程数 - > 1024,每块最大共享存储器数 - > 49152,总常数存储器 - > 65536,翘曲尺寸 - > 32,最大间距 - > 2147483647,每块最大寄存器 - > 32768,纹理对准 - > 512,多处理器计数 - > 14,核心计数 - > 448,执行超时 - > 0,集成 - >假,可以映射主机存储器 - >真,计算模式 - >默认,纹理1D宽度 - > 65536,纹理2D宽度 - > 65536,纹理2D高度 - > 65535,纹理3D宽度 - > 2048,纹理3D高度 - > 2048 ,Texture3D Depth-> 2048,Texture2D Array Width-> 16384,Texture2D Array Height-> 16384,Texture2D Array Slices-> 2048,Surface Alignment-> 512,Concurrent Kernels-> True,ECC Enabled-&gt ; True,Total Memory-> 2817982462},
所有这些代码都设置了3D数组的值等于CUDA使用的索引:
__global __ void cudaMatExp(
float *matrix1, float *matrixStore, int lengthx, int lengthy, int lengthz){
long UniqueBlockIndex = blockIdx.y * gridDim.x + blockIdx.x;
long index = UniqueBlockIndex * blockDim.z * blockDim.y * blockDim.x +
threadIdx.z * blockDim.y * blockDim.x + threadIdx.y * blockDim.x +
threadIdx.x;
if (index < lengthx*lengthy*lengthz) {
matrixStore[index] = index;
}
}
由于某种原因,一旦我的3D数组的尺寸变得太大,索引就会停止。
我尝试了不同的块尺寸(blockDim.y by blockDim.z的blockDim.x):
8x8x8仅提供正确的索引,直到数组维度12x12x12
9x9x9仅提供正确的索引,直到数组维度14x14x14
10x10x10仅提供正确的索引,直到阵列尺寸为15x15x15
对于大于这些尺寸的尺寸,所有不同的块尺寸最终会再次开始增加,但它们永远不会达到dim ^ 3-1的值(这是cuda线程应达到的最大折射率)
以下是一些说明此行为的图表:
例如:这是在x轴上绘制3D阵列的维度(x x x),在y轴上绘制cuda执行期间处理的最大索引号。此特定图表的块尺寸为10x10x10。
这是生成该图的(Mathematica)代码,但是当我运行这个时,我使用了1024x1x1的块尺寸:
CUDAExp = CUDAFunctionLoad[codeexp, "cudaMatExp",
{{"Float", _,"Input"}, {"Float", _,"Output"},
_Integer, _Integer, _Integer},
{1024, 1, 1}]; (*These last three numbers are the block dimensions*)
max = 100; (* the maximum dimension of the 3D array *)
hold = Table[1, {i, 1, max}];
compare = Table[i^3, {i, 1, max}];
Do[
dim = ii;
AA = CUDAMemoryLoad[ConstantArray[1.0, {dim, dim, dim}], Real,
"TargetPrecision" -> "Single"];
BB = CUDAMemoryLoad[ConstantArray[1.0, {dim, dim, dim}], Real,
"TargetPrecision" -> "Single"];
hold[[ii]] = Max[Flatten[
CUDAMemoryGet[CUDAExp[AA, BB, dim, dim, dim][[1]]]]];
, {ii, 1, max}]
ListLinePlot[{compare, Flatten[hold]}, PlotRange -> All]
这是相同的情节,但现在正在绘制x ^ 3以与它应该的位置进行比较。请注意,在数组的维度> 32
之后,它会发散
我测试3D数组的尺寸,看看索引的走向,并将其与dim ^ 3-1进行比较。例如。对于dim = 32,cuda max索引是32767(其为32 ^ 3 -1),但是对于dim = 33,当它应该是35936(33 ^ 3 -1)时,cuda输出是33791。请注意,33791-32767 = 1024 = blockDim.x
问题:
有没有办法正确索引尺寸大于Mathematica中块尺寸的数组?
现在,我知道有些人在他们的索引方程中使用__mul24(threadIdx.y,blockDim.x)来防止位乘法错误,但在我的情况下似乎没有帮助。
另外,我看到有人提到你应该使用-arch = sm_11编译代码,因为默认情况下它是为计算能力1.0编译的。我不知道Mathematica是否就是这种情况。我假设CUDAFunctionLoad []知道用2.0能力编译。有人知道吗?
任何建议都会非常有用!
答案 0 :(得分:1)
因此,Mathematica有一种处理网格维度的隐藏方法,将网格维度修复为可行的东西,你必须在你正在调用的函数的末尾添加另一个数字。
参数表示要启动的线程数(或网格尺寸乘以块尺寸)。
例如,在上面的代码中:
CUDAExp =
CUDAFunctionLoad[codeexp,
"cudaMatExp", {
{"Float", _, "Input"}, {"Float", _,"Output"},
_Integer, _Integer, _Integer},
{8, 8, 8}, "ShellOutputFunction" -> Print];
(8,8,8)表示块的尺寸。
当您在mathematica中调用CUDAExp[]
时,您可以添加一个参数来表示要启动的线程数:
在这个例子中,我终于得到了以下内容:
// AA and BB are 3D arrays of 0 with dimensions dim^3
dim = 64;
CUDAExp[AA, BB, dim, dim, dim, 4089];
请注意,当您使用CUDAFunctionLoad []进行编译时,它只需要5个输入,第一个是您传递的数组(维度dim x dim x dim
),第二个是存储它的内存。第三,第四和第五是尺寸。
当你传递第6个数据时,mathematica将其翻译为gridDim.x * blockDim.x
,因此,因为我知道我需要gridDim.x = 512以便处理数组中的每个元素,所以我将此数字设置为相等到512 * 8 = 4089。
我希望这对未来遇到这个问题的人来说是明确和有用的。