且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何修改zip迭代器的内容

更新时间:2022-06-18 23:58:35

获取仿函数类型以匹配推力传递的类型和推力所需的类型有时可能很棘手.这是一种使用模板的方法,可以让编译器确定所需的确切类型:

Getting the functor types to match the types passed by thrust and required by thrust can sometimes be tricky. Here is one possible approach using templating to let the compiler decide the exact type needed:

$ cat t334.cu
#include <thrust/transform.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/execution_policy.h>
#include <iostream>
#include <thrust/copy.h>

struct modify_tuple
{
    int _factor;
    modify_tuple(int factor) : _factor(factor) { }
template <typename T>
    __host__ __device__ thrust::tuple<float,float,float> operator()(const T a) const
    {
        thrust::tuple<float,float,float>  res = a;
        thrust::get<0>(res) *= _factor;
        thrust::get<1>(res) *= _factor;
        thrust::get<2>(res) *= _factor;
        return res;
    }
};

int main(void)
{
    thrust::device_vector<float> X(3);
    thrust::device_vector<float> Y(3);
    thrust::device_vector<float> Z(3);
    thrust::device_vector<float> RX(3);
    thrust::device_vector<float> RY(3);
    thrust::device_vector<float> RZ(3);

    X[0]=0,    X[1]=1,    X[2]=2;
    Y[0]=4,    Y[1]=5,    Y[2]=6;
    Z[0]=7,    Z[1]=8,    Z[2]=9;

    thrust::copy_n(X.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(Y.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(Z.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::transform(thrust::device, thrust::make_zip_iterator(thrust::make_tuple(X.begin(), Y.begin(), Z.begin())),thrust::make_zip_iterator(thrust::make_tuple(X.end(), Y.end(), Z.end())), thrust::make_zip_iterator(thrust::make_tuple(RX.begin(), RY.begin(), RZ.begin())), modify_tuple(2));
    thrust::copy_n(X.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(Y.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(Z.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(RX.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(RY.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;
    thrust::copy_n(RZ.begin(), 3, std::ostream_iterator<float>(std::cout, ","));
    std::cout << std::endl;

    return 0;
}
$ nvcc -o t334 t334.cu
$ ./t334
0,1,2,
4,5,6,
7,8,9,
0,1,2,
4,5,6,
7,8,9,
0,2,4,
8,10,12,
14,16,18,
$

传递给函子的确切基础类型似乎是迭代器元组引用,而返回类型是具有float值的普通元组.

The exact underlying type passed to the functor appears to be a tuple-of-iterator-references, whereas the return type is an ordinary tuple of float values.

请注意,可以直接在函子中修改a.通常看来,a是按值传递给函子的,但在这种情况下,推力使用的是迭代器元组引用,因此在函子中修改a的副作用是它将修改传递给函子的实际推力矢量值(即源矢量).因此,我在上面的代码中选择了一种避免这种情况的实现,但是对于您的原始代码,很明显,您打算对源向量进行就地修改.因此,如果需要,可以简化函子以直接修改a.

Note that it is possible to modify a directly in the functor. It would normally appear that a is passed by value to the functor, but in this case thrust is using a tuple-of-iterator-references, and so a side effect of modifying a in the functor is that it will modify the actual thrust vector values passed to the functor (i.e. the source vector(s)). Therefore I have chosen a realization in the above code that avoids this, however in the case of your original code, its evident you intended to do an in-place modification of the source vectors. Therefore, the functor could be simplified to modify a directly, if desired.