GPU高性能计算CUDA编程:使用寄存器交换4个像素

GPU高性能计算CUDA编程:使用寄存器交换4个像素

声明:本文不做商用

在制定下一步改进计划时,我们将保留那些已经起作用的并改进那些还没有提升的地方。在Hflip7()中,我们通过读取3个自然的int大小的元素来读取4个像素的方式非常完美。该核函数的问题是,一旦进人共享内存,我们仍然按照unsignedchar的大小(字节)来处理数据。从共享内存(或任何类型的内存)中读取和写人这些非自然大小元素的操作效率非常低。在核函数Hflip7()中,每个字节交换都需要访问3次共享内存,每次都是非自然的 unsigned char 大小。
代码10.3中所示的Hflip8()的想法是将非自然大小的访问操作放在核心内部进行,因为核心在操作字节大小的数据元素时效率更高。为此,Hfip8()分配了6个变量A、B、C、D、E、F,它们都是具有自然大小的unsignedint(32位)类型。我们不再使用共享内存。对全局存储器(GM)的唯一访问是从它那儿以32位大小读取数据,如下所示:

ui  A, B, C, D, E, F;

// read 4 pixel blocks (12B = 3 int's) into 3 long registers
A = ImgSrc32[MYsrcIndex];
B = ImgSrc32[MYsrcIndex + 1];
C = ImgSrc32[MYsrcIndex + 2];

这是将翻转后的像素写回GM之前的唯一一次GM访问。需要注意的是GM中的数据以小端格式存储,与共享内存相反。参见【0voice C++】所以,Hflip8()的目标是将如下所示的A、B、C

// 现在:   A=[B1,R0,G0,B0]  B=[G2,B2,R1,G1]  C=[R3,G3,B3,R2]

转换为如下所示的 D、E、F:

// 我们的目标:  D=[B2,R3,G3,B3]  E=[G1,B1,R2,G2]  F=[R0,G0,B0,R1]

这种方法高效的原因在于,由于核函数中需要的变量比较少,因此编译器可以轻松地将所有这些变量映射到核心寄存器中,这使得对它们的操作非常高效。此外,在字节的处理过程中,核心使用的只是shif、AND、OR操作,它们是核心中ALU的基本操作,可以由编译器选择编译为最快的指令。

举个例子,让我们分析下面的C语句:

// 现在:   A=[B1,R0,G0,B0]  B=[G2,B2,R1,G1]  C=[R3,G3,B3,R2]
E = (B << 24) | (B >> 24) | ((A >> 8) & 0x00FF0000) | ((C << 8) & 0x0000FF00);

这里有4个桶式shif/AND运算产生如下的32位值:

(B<<24) = [G1,0,0,0] (B>>24) = [0,0,0,G2]
((A>>8) & 0x00FF0000) = ([0,B1,RO,G0] & [00,FF,00,00]) = [0,B1, 0, 0]
((C<<8) & 0x0000FF00) = ([G3,B3,R2,0] & [00,00,FF,00]) = [0,0, R2, 0]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值