如何执行扫描扭曲

时间:2014-03-08 10:41:05

标签: matlab cuda

我正在尝试理解以下代码的执行

template < class OP , ScanKind Kind , class T >
__device__ T scan_warp ( volatile T * ptr , const unsigned int idx = threadIdx.x )
{
     const unsigned int lane = idx & 31; // index of thread in warp (0..31)
/*1*/if ( lane >= 1) ptr [ idx ] = OP :: apply ( ptr [ idx - 1] , ptr [ idx ]);
/*2*/if ( lane >= 2) ptr [ idx ] = OP :: apply ( ptr [ idx - 2] , ptr [ idx ]);
/*3*/if ( lane >= 4) ptr [ idx ] = OP :: apply ( ptr [ idx - 4] , ptr [ idx ]);
/*4*/if ( lane >= 8) ptr [ idx ] = OP :: apply ( ptr [ idx - 8] , ptr [ idx ]);
/*5*/if ( lane >= 16) ptr [ idx ] = OP :: apply ( ptr [ idx - 16] , ptr [ idx ]);
/*6*/if( Kind == inclusive ) return ptr [ idx ];
     else return ( lane >0) ? ptr [ idx -1] : OP :: identity ();
}

通过写一个例子。

示例:

输入[ 3 4 5 2 1 7 8 9 ] 正确输出: [ 3 7 12 14 15 22 30 39 ]

  • 第1步: threadIdx.x = 0lane = 0输出[ 3 4 5 2 1 7 8 9 ],(无if语句执行)< / LI>
  • 第2步: threadIdx.x = 1lane = 1输出[ 3 7 5 2 1 7 8 9 ],(/ * 1 * /已执行)
  • 第3步: threadIdx.x = 2lane = 2 outputTemp [ 3 7 12 2 1 7 8 9 ],((/ * 1 * /已执行)), outputFinal [ 3 7 15 2 1 7 8 9 ],(/ * 2 * /已执行)

step3 中,outputTemp通过应用第一个output语句从 step2 中的if获取。 outputFinal是通过在if中应用第二个outputTemp语句获得的。所以在最终输出的第三个元素中有一个错误。而不是12我们有15。

问题:

  1. 我对线程执行怀疑论者有什么问题?你能描述一下线程执行吗?
  2. 为什么我们使用const unsigned int lane = idx & 31;检查if语句中的条件,而不是idx自己的条件。我的意思是,如果idx = [0 1...31] lane也是[0 1 2...31]
  3. 有没有可能的方法来在matlab中可视化线程执行?
  4. 非常感谢你的时间。

1 个答案:

答案 0 :(得分:2)

  1. 您显示的代码是 warp 扫描操作,这意味着它是由给定warp中的所有32个线程同时执行的。假设OP::apply是一个加法运算,这意味着下面的中间值序列

    输入[3 4 5 2 1 7 8 9]

    步骤1 [3 7 9 7 3 8 15 17]车道1,2,3,4,5,6,7执行OP::apply( ptr[idx-1], ptr[idx])

    步骤2 [3 7 12 14 12 15 18 25]车道2,3,4,5,6,7执行OP::apply( ptr[idx-2], ptr[idx])

    步骤3 [3 7 12 14 15 22 30 39]车道4,5,6,7执行OP::apply( ptr[idx-4], ptr[idx])

    另请注意,此代码预计会有32个输入值,因此尝试在您提供的示例上运行它会产生运行时错误。

  2. 因为典型的块包含超过32个线程(即多于1个warp),并且认为该代码可用于块中的任何warp。因此,threadIdx.x = 0..31的相同计算也可用于threadIdx.x = 128..159threadIdx.x = 992..1023

  3. 可能,但笔和纸是一个更好的工具。