我对CGMA的计算感到困惑。我知道CGMA =操作次数/内存提取次数。首先,当x = g_A[idx]
时,我应该将写操作计数到x
还是忽略它,因为它存储在寄存器中?同样,在z = (x*y) + (y/x) + (y-x);
中,我应该计算x
和y
的读数作为CGMA计算中的内存读数吗?最后,我应该计算内核函数中的所有操作(那五行)吗?
__global__ void PerformSomeOperations(int* g_A,int* g_B,int* g_C, int Size)
{
const int idx = threadIdx.x + (blockIdx.x*blockDim.x);
if(idx < Size)
{
int x = g_A[idx];
int y = g_B[idx];
int z = 0;
z = (x*y) + (y/x) + (y-x);
g_C[idx] = z;
}
}
答案 0 :(得分:3)
与您的内核相对应的反汇编代码(为compute_20,sm_20
编译)是以下
/*0000*/ MOV R1, c[0x1][0x100];
/*0008*/ S2R R0, SR_CTAID.X;
/*0010*/ S2R R2, SR_TID.X;
/*0018*/ IMAD R0, R0, c[0x0][0x8], R2;
/*0020*/ ISETP.GE.AND P0, PT, R0, c[0x0][0x2c], PT;
/*0028*/ @P0 EXIT ;
/*0030*/ SHL R0, R0, 0x2;
/*0038*/ IADD R2, R0, c[0x0][0x20];
/*0040*/ IADD R3, R0, c[0x0][0x24];
/*0048*/ IADD R0, R0, c[0x0][0x28];
/*0050*/ LD R2, [R2]; R2 = x = g_A[idx]
/*0058*/ LD R3, [R3]; R3 = y = g_B[idx]
/*0060*/ I2I.S32.S32 R5, |R2|;
/*0068*/ I2F.F32.U32.RP R4, R5; R4 = (float)x
/*0070*/ MUFU.RCP R4, R4; R4 = 1/R4
/*0078*/ IADD32I R4, R4, 0xffffffe;
/*0080*/ F2I.FTZ.U32.F32.TRUNC R4, R4;
/*0088*/ IMUL.U32.U32 R6, R5, R4; R6 = x * (1/y)
/*0090*/ I2I.S32.S32 R7, -R6;
/*0098*/ I2I.S32.S32 R6, |R3|;
/*00a0*/ IMAD.U32.U32.HI R7, R4, R7, R4;
/*00a8*/ IMUL.U32.U32.HI R4, R7, R6;
/*00b0*/ LOP.XOR R7, R3, R2;
/*00b8*/ IMAD.U32.U32 R6, -R5, R4, R6;
/*00c0*/ ISETP.GE.AND P1, PT, R7, RZ, PT;
/*00c8*/ ISETP.LE.U32.AND P0, PT, R5, R6, PT;
/*00d0*/ @P0 ISUB R6, R6, R5;
/*00d8*/ @P0 IADD R4, R4, 0x1;
/*00e0*/ ISETP.GE.U32.AND P0, PT, R6, R5, PT;
/*00e8*/ LOP.PASS_B R6, RZ, ~R2;
/*00f0*/ ISUB R5, R3, R2;
/*00f8*/ @P0 IADD R4, R4, 0x1;
/*0100*/ @!P1 I2I.S32.S32 R4, -R4;
/*0108*/ ICMP.EQ R4, R6, R4, R2;
/*0110*/ IADD R4, R5, R4;
/*0118*/ IMAD R2, R3, R2, R4;
/*0120*/ ST [R0], R2;
/*0128*/ EXIT ;
从上面的代码中,有以下浮点运算
I2F.F32.U32.RP R4, R5; Integer to Float conversion
MUFU.RCP R4, R4; Multifunction Floating Point Operation (Reciprocal)
F2I.FTZ.U32.F32.TRUNC R4, R4; Float to Integer conversion
这些操作似乎与(x/y)
有关,3
是两个整数之间的一个除法,但需要转换为浮点。我真的不知道转换是否被视为浮点运算。我在代码中没有看到任何其他浮点运算。
全局内存操作如下LD R2, [R2];
LD R3, [R3];
ST [R0], R2;
CGMA = 3/3 = 1
对于您的情况我会说int2float
(将float2int
和{{1}}次转化计为浮点运算。)
答案 1 :(得分:1)
看起来 CGMA 代表计算全局内存访问并定义为数字 每次访问全局内存时执行的浮点计算 CUDA计划的区域。
计算比率的最佳方法是在CUDA探查器中运行程序,并使用性能计数器进行内存访问和浮点运算。根据我发现的定义,你的内核的CGMA为零,因为它执行整数运算,而不是浮点运算。如果更改定义,则x = g_A[idx]
是一个读操作,没有写操作。这是因为寄存器文件没有存储在全局存储器中(CGMA中的“G”)。 z = (x*y) + (y/x) + (y-x);
中没有全局内存读取,因此将其视为5次操作。如果所有线程都使用idx < Size
运行,则您有3次全局内存访问和8次操作。但请注意,在CUDA中,全局内存访问的性能取决于它们是否合并。许多合并的内存访问比一些未合并的内存访问运行得快得多。因此,CGMA不一定能准确描述内核的性能潜力。
参考文献:
http://www.greatlakesconsortium.org/events/GPUMulticore/Chapter4-CudaMemoryModel.pdf
http://cs.nyu.edu/courses/spring12/CSCI-GA.3033-012/lecture6.pdf