2013-10-15 46 views
0

我对CGMA的计算感到困惑。我知道CGMA =运算次数/内存提取次数。首先,当x = g_A[idx]时,我应该将写操作计数到x还是忽略它,因为它存储在寄存器中?同样,在z = (x*y) + (y/x) + (y-x);中,我应该将读取的xy作为计算CGMA中的内存读数吗?最后,我是否应该计算内核函数中的所有操作(这五行)?CUDA中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; 
    } 
} 
+1

读取和写入寄存器不计入GMA。 2从'g_A'和'g_B'计数中读取。写入'g_C'是很重要的。为了使算术计算正确,您需要查看SASS代码,或者您可以简单地从源代码或PTX代码进行估算。您应该计算所有算术运算,包括那些与'idx'有关的运算操作 –

+0

操作符是否被算作操作? – Shibli

+0

是的。在内核中执行的任何算术计数(例如甚至不明显的地址计算算法)。 –

回答

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

2

对应你的内核(编译为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对于你的情况(计数int2floatfloat2int转换为浮点运算)。

+0

你编译了哪个体系结构?有趣的是,它没有整数分频硬件。 –

+1

@RogerDahl Fermi:'compute_20,sm_20'。 – JackOLantern