Mathematica中的CUDAFunctionLoad - 索引问题

时间:2011-05-27 20:43:59

标签: indexing cuda wolfram-mathematica mathematica-8

我正在尝试调试我在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。

enter image description here

这是生成该图的(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

之后,它会发散

enter image description here

我测试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能力编译。有人知道吗?

任何建议都会非常有用!

1 个答案:

答案 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。

我希望这对未来遇到这个问题的人来说是明确和有用的。