CUDA循环展开

Zigiggurats

我在CUDA中循环展开时遇到一些问题。

在普通序列号中:

//serial basic:
for(int i = 0; i < n; i++){
    c[i] = a[i] + b[i];}

//serial loop unroll:
for(int i = 0; i < n/4; i++){
    c[i] = a[i] + b[i];
    c[i+1] = a[i+1] + b[i+1];
    c[i+2] = a[i+2] + b[i+2];
    c[i+3] = a[i+3] + b[i+3];} 

因此,我认为CUDA循环展开如下所示:

int i = 2*(threadIdx.x + blockIdx.x * gridDim.x);
a[i+0] = b[i+0] + c[i+0];
a[i+1] = b[i+1] + c[i+1];

但是在CUDA手册中,我无法理解展开的示例

这是一个普通的GlobalWrite内核:

__global__ void GlobalWrites( T *out, T value, size_t N )
{
for(size_t i = blockIdx.x*blockDim.x+threadIdx.x;
    i < N;
    i += blockDim.x*gridDim.x ) {
    out[i] = value;
    } 
 }

展开内核:

template<class T, const int n> __global__ void Global_write(T* out, T value, size_t N){
size_t i;
for(i = n*blockDim.x*blockIdx.x + threadIdx.x;
    i < N - n*blockDim.x*blockIdx.x;
    i += n*gridDim.x*blockDim.x;)
    for(int j = 0; j < n; i++){
        size_t index = i + j * blockDim.x;
        outp[index] = value;
    }
for ( int j = 0; j < n; j++ ) {
    size_t index = i+j*blockDim.x;
    if ( index<N ) out[index] = value;
}}

我知道此内核使用较少的块,但也许有人可以解释为什么它会更好(n = 4,10%加速)。

看守人

如果不是很明显,因为n它是模板参数,所以在编译时是恒定的。这意味着编译器可以通过展开自由地优化恒定行程计数循环。因此,对于您提到的n = 4情况,删除模板魔术并手动展开循环是有启发性的:

template<class T> 
__global__ void Global_write(T* out, T value, size_t N)
{
    size_t i;
    for(i = 4*blockDim.x*blockIdx.x + threadIdx.x;
        i < N - 4*blockDim.x*blockIdx.x;
        i += 4*gridDim.x*blockDim.x;) {
            out[i + 0 * blockDim.x] = value;
            out[i + 1 * blockDim.x] = value;
            out[i + 2 * blockDim.x] = value;
            out[i + 3 * blockDim.x] = value;
    }
    if ( i+0*blockDim.x < N ) out[i+0*blockDim.x] = value;
    if ( i+1*blockDim.x < N ) out[i+1*blockDim.x] = value;
    if ( i+2*blockDim.x < N ) out[i+2*blockDim.x] = value;
    if ( i+3*blockDim.x < N ) out[i+3*blockDim.x] = value;
}

展开的内部循环产生四个完全独立的写入,这些写入被合并。正是这种指令级并行性使代码具有更高的指令吞吐量和更高的性能。如果您还没看过的话,我强烈建议您在几年前的GTC会议上推荐瓦西里·沃尔科夫(Vasily Volkov)的“展开平行循环”他的演讲为为什么这种类型的循环展开是CUDA中的优化提供了理论背景。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

嵌套循环展开

来自分类Dev

根据CUDA 6.5在循环展开时输出错误

来自分类Dev

根据CUDA 6.5在循环展开时输出错误

来自分类Dev

XNA优化-循环展开?

来自分类Dev

C循环展开限制?

来自分类Dev

GCC 5.1循环展开

来自分类Dev

SSE内部和循环展开

来自分类Dev

C ++:循环优化和循环展开(循环或不循环)

来自分类Dev

使用Scala设计过滤器-用于循环展开

来自分类Dev

循环展开?在Julia中进行元编程

来自分类Dev

GCC循环展开标志真的有效吗?

来自分类Dev

使用Ivy Bridge和Haswell循环展开以实现最大吞吐量

来自分类Dev

为什么Hotspot JIT不对长计数器执行循环展开?

来自分类Dev

如何在运行时实现基于2的循环展开以进行优化

来自分类Dev

为什么循环展开会在ARM Cortex-a53上带来如此大的提速?

来自分类Dev

C++ Introsort 中的手动循环展开运行不正确

来自分类Dev

CUDA循环在数组添加中展开

来自分类Dev

除了使用循环展开之外,还有没有其他方法可以优化向量矩阵乘法?

来自分类Dev

线程之间保留的Cuda展开循环变量

来自分类Dev

静态数组的展开循环

来自分类Dev

展开循环,何时使用

来自分类Dev

Cython自动展开循环

来自分类Dev

在C中展开循环

来自分类Dev

静态数组的展开循环

来自分类Dev

停止循环并展开活动元素

来自分类Dev

CUDA中的经线展开期间的线程同步

来自分类Dev

展开循环有效,for 循环无效

来自分类Dev

cuda的多线程for循环

来自分类Dev

对于在预处理阶段展开的循环宏?