适当的推力要求减法

时间:2014-12-10 09:48:06

标签: cuda thrust

来自here

假设dev_X是一个向量。

int * X = (int*) malloc( ThreadsPerBlockX * BlocksPerGridX * sizeof(*X) );


for ( int i = 0; i < ThreadsPerBlockX * BlocksPerGridX; i++ )
    X[ i ] = i;

// create device vectors
thrust::device_vector<int> dev_X ( ThreadsPerBlockX * BlocksPerGridX );

//copy to device
thrust::copy( X , X + theThreadsPerBlockX * theBlocksPerGridX , dev_X.begin() );

以下是减法:

   thrust::transform( dev_Kx.begin(), dev_Kx.end(), dev_X.begin() , distX.begin() , thrust::minus<float>() );
dev_Kx - dev_X.

我想使用整个dev_Kx向量(因为它使用的是因为它从.begin到.end())和整个dev_X向量。

以上代码使用dev_X.begin()

这是否意味着它将使用整个dev_X向量?从头开始? 或者我必须使用另一个额外的参数来指向dev_X.end()? (因为在上面的函数调用中我不能只使用这个额外的参数)

另外,例如:

如果我想使用

thrust::transform( dev_Kx, dev_Kx + i , dev_X.begin() ,distX.begin() , thrust::minus<int>() ); 

然后dev_Kx会从0到i和dev_X.begin()?它将使用相同的长度? (0到i?)或者它将使用dev_X的长度?

1 个答案:

答案 0 :(得分:7)

许多thrust(和标准库)函数将范围作为第一个参数,然后假设所有其他迭代器都由相同大小的容器支持。范围是一对迭代器,表示序列的开头 end

例如:

thrust::copy(
    X.begin(),    // begin input iterator
    X.end(),      // end input iterator
    dev_X.begin() // begin output iterator
);

这会将X的全部内容复制到dev_X。为什么不需要dev_X.end()?因为thrust要求您(程序员)需要正确调整dev_X的大小,以便能够包含至少与输入范围中一样多的元素。如果您不满足该保证,则行为未定义。

执行此操作时:

thrust::transform(
    dev_Kx.begin(), // begin input (1) iterator
    dev_Kx.end(),   // end input (1) iterator
    dev_X.begin(),  // begin input (2) iterator
    distX.begin(),  // output iterator
    thrust::minus<float>()
);

thrust看到的输入范围是dev_Kx.begin()dev_Kx.end()。它的显式大小为dev_Kx.end() - dev_Kx.begin()。为什么不需要dev_X.end()distX.end()?因为它们的隐式大小也是dev_Kx.end() - dev_Kx.begin()。例如,如果dev_Kx中有10个元素,则transform将:

  • 使用dev_Kx
  • 的10个元素
  • 使用dev_X的10个元素(必须至少包含 10个元素)
  • 执行减法并将10个结果存储在distX中,该结果必须至少能够容纳 10个元素。

也许看看实施会消除任何疑虑。这是一些伪代码:

void transform(InputIterator input1_begin, InputIterator input1_end,
               InputIterator input2_begin, OutputIterator output,
               BinaryFunction op) {
    while (input1_begin != input1_end) {
        *output++ = op(*input1_begin++, *input2_begin++);
    }
}

注意如何只需要一个结束迭代器。


在不相关的说明中,以下内容:

int * X = (int*) malloc( ThreadsPerBlockX * BlocksPerGridX * sizeof(*X) );
for ( int i = 0; i < ThreadsPerBlockX * BlocksPerGridX; i++ )
    X[ i ] = i;

可以用更惯用,更不容易出错的C ++重写为:

std::vector<int> X(ThreadsPerBlockX * BlocksPerGridX);
std::iota(X.begin(), X.end(), 0);