Thursday, September 17, 2009

图解CUDA中用多线调度执行来隐藏内存访问延迟的机制

近在捣鼓CUDA,实现的几个小算法速度能提高到40~50x单线CPU的程度。可惜现在这边弄这个的人不多,基本没有“真人交流”。希望今后能用来做一些实际的项目,发挥一下潜能。嘿嘿。

最近应该会写一些心得,记录一下学习过程。我其实是一直有心做这样的事情,只是懒…… 从今天开始,哈哈。

图解CUDA中用多线调度执行来隐藏内存访问延迟的机制

GPU
和device RAM之间带宽虽宽(如GTX285的150GB/s),不过内存访问延迟依旧很大(400~600 cycles)。CPU用cache可以很好的解决内存延迟;不过GPU由于要处理的通常是大规模的数据集,源数据的locality或许并不高,即便加上很大的data cache效果也不一定好,所以索性放弃了data cache,换而采用用户可控的shared memory来开发data locality。最重要的,虽然GPU的一个处理器(SM - Streaming Multiprocessor)同时只能执行一个warp的线程(32个),但却可以容纳大量的活动线程(active threads <= 1024)。当一个warp由于访问内存而被阻塞时,SM可以马上转为执行其他ready的warp,直到其被内存访问阻塞。只要这样转一圈的时间(执行完一圈其他的warps再转回来到第一个被阻塞的warp的时间)大于600 cycle的延迟,这个延迟就被隐藏了。

下图示意了内存访问延迟不能被完全隐藏的情况。假设SM上只有4个warp,他们需要从内存里面读取数据,在上面计算一把,循环这个过程。当然,我们也可以看成每个warp计算一次就终止了,之后新的warp会产生出来,代替原来那个warp的位置。从图里面很容易看出来虚线部分的latency是怎么被隐藏的;也很容易看出来因为每个warp的计算不够长,所以没有能够隐藏掉所有的latency。


放到现有的G200的architecture上来,每个SM最多1024个active thread,也就是32个warp。每个warp执行一个基本指令需要4个cycle。也就是说,要隐藏600 cycles需要每个warp平均执行 600/4/32 = 4.69个基本指令。这就是为什么推荐compute to memory ratio至少大于5的原因。这还是建立在理想的1024个active thread的情况下的。如果SM上thread少,这个比例还要提高。

3 comments:

alva said...

加油加油!

Construction World said...

I wish I can read your language translated to English that way your write ups on architecture would have interested me.

David James said...

Apna Showroom Men's and Women's Metal Hair Bands (Black) Combo set of 5 (zigzag_hair_band Metal
yeah thans ful heart for her

APNA SHOWROOM Bra for Women Combo Pack of 6 Cup Size 34 (B) Non-Wired Multicolor Everyday Cotton Bra Daily use
she is slim beautiful virgin and pure heart
Apna Showroom Women's Nylon Underskirt Pantyhose Stockings for women or girls free size black stockings
dedicated towards family life