Cuda 使用eigen::Matrix修改zip迭代器会得到错误的结果

Cuda 使用eigen::Matrix修改zip迭代器会得到错误的结果,cuda,iterator,zip,tuples,thrust,Cuda,Iterator,Zip,Tuples,Thrust,我有三组点X,Y,Z。我打算使用Eigen::Matrix4f应用一个变换。我使用一个zip迭代器和一个转换操作符来完成它。程序进行编译,但结果仅部分正确。这篇文章的灵感来自 转变 A=[012;345;678;1111]和M=[1234;56788;9101112;1315116]使用M*A应该得到:R=[283440;6886104;108138] 然而,它给出了:R=[283440;208251294;241029053400] 正在正确修改X值。但是,Y和Z值有故障 我的代码和Cmake

我有三组点X,Y,Z。我打算使用Eigen::Matrix4f应用一个变换。我使用一个zip迭代器和一个转换操作符来完成它。程序进行编译,但结果仅部分正确。这篇文章的灵感来自

转变 A=[012;345;678;1111]和M=[1234;56788;9101112;1315116]使用M*A应该得到:R=[283440;6886104;108138] 然而,它给出了:R=[283440;208251294;241029053400]

正在正确修改X值。但是,Y和Z值有故障

我的代码和CmakeList如下:

#include <thrust/iterator/zip_iterator.h>
#include <thrust/execution_policy.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>

#include <Eigen/Dense>
#include <iostream>

typedef thrust::device_vector<float>::iterator                     FloatIterator;
typedef thrust::tuple<FloatIterator, FloatIterator, FloatIterator> FloatIteratorTuple;
typedef thrust::zip_iterator<FloatIteratorTuple>                   Float3Iterator;

typedef thrust::tuple<float,float,float> Float3;

struct modify_tuple
{
    Eigen::Matrix4f _Mat4f;
    modify_tuple(Eigen::Matrix4f Mat4f) : _Mat4f(Mat4f) { }
    __host__ __device__ Float3 operator()(Float3 a) const
    {

        Eigen::Vector4f V(thrust::get<0>(a), thrust::get<1>(a), thrust::get<2>(a), 1.0);

    V=_Mat4f*V;

    Float3  res=thrust::make_tuple( V(0,0), V(1,0), V(2,0) );

        return res;
    }
};


int main(void)
{
    thrust::device_vector<float> X(3);
    thrust::device_vector<float> Y(3);
    thrust::device_vector<float> Z(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;

    std::cout << "X,Y,Z before transformation="<< std::endl;
    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;


    Float3Iterator P_first = thrust::make_zip_iterator(make_tuple(X.begin(), Y.begin(), Z.begin()));
    Float3Iterator P_last  = thrust::make_zip_iterator(make_tuple(X.end(),   Y.end(),   Z.end()));


    Eigen::Matrix4f M;
    M(0,0)= 1; M(0,1)= 2;  M(0,2)= 3;  M(0,3)= 4; 
    M(1,0)= 5; M(1,1)= 6;  M(1,2)= 7;  M(1,3)= 8; 
    M(2,0)= 9; M(2,1)= 10; M(2,2)= 11; M(2,3)= 12; 
    M(3,0)= 13; M(3,1)= 14;  M(3,2)= 15;  M(3,3)= 16;

    thrust::transform(thrust::device, P_first,P_last, P_first, modify_tuple(M));

    std::cout << "X, Y, Z after transformation="<< std::endl;
    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;


    return 0;
}

也许你只需要得到最新的Eigen

我在Fedora27上使用了CUDA 9.2,并从中获取了最新的eigen

然后我编译并运行了您的代码,如下所示:

$ cat t21.cu
#include <thrust/iterator/zip_iterator.h>
#include <thrust/execution_policy.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>

#include <Eigen/Dense>
#include <iostream>

typedef thrust::device_vector<float>::iterator                     FloatIterator;
typedef thrust::tuple<FloatIterator, FloatIterator, FloatIterator> FloatIteratorTuple;
typedef thrust::zip_iterator<FloatIteratorTuple>                   Float3Iterator;

typedef thrust::tuple<float,float,float> Float3;

struct modify_tuple
{
    Eigen::Matrix4f _Mat4f;
    modify_tuple(Eigen::Matrix4f Mat4f) : _Mat4f(Mat4f) { }
    __host__ __device__ Float3 operator()(Float3 a) const
    {

        Eigen::Vector4f V(thrust::get<0>(a), thrust::get<1>(a), thrust::get<2>(a), 1.0);

    V=_Mat4f*V;

    Float3  res=thrust::make_tuple( V(0,0), V(1,0), V(2,0) );

        return res;
    }
};


int main(void)
{
    thrust::device_vector<float> X(3);
    thrust::device_vector<float> Y(3);
    thrust::device_vector<float> Z(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;

    std::cout << "X,Y,Z before transformation="<< std::endl;
    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;


    Float3Iterator P_first = thrust::make_zip_iterator(make_tuple(X.begin(), Y.begin(), Z.begin()));
    Float3Iterator P_last  = thrust::make_zip_iterator(make_tuple(X.end(),   Y.end(),   Z.end()));


    Eigen::Matrix4f M;
    M(0,0)= 1; M(0,1)= 2;  M(0,2)= 3;  M(0,3)= 4;
    M(1,0)= 5; M(1,1)= 6;  M(1,2)= 7;  M(1,3)= 8;
    M(2,0)= 9; M(2,1)= 10; M(2,2)= 11; M(2,3)= 12;
    M(3,0)= 13; M(3,1)= 14;  M(3,2)= 15;  M(3,3)= 16;

    thrust::transform(thrust::device, P_first,P_last, P_first, modify_tuple(M));

    std::cout << "X, Y, Z after transformation="<< std::endl;
    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;


    return 0;
}
$ nvcc -std=c++11 -I/path/to/eigen/eigen-eigen-71546f1a9f0c t21.cu -o t21 --expt-relaxed-constexpr
$ ./t21
X,Y,Z before transformation=
0,1,2,
4,5,6,
7,8,9,
X, Y, Z after transformation=
33,39,45,
81,99,117,
129,159,189,
$

您对问题和代码的描述中的向量与Matrix4x4*Vector4X1=Vector4X1不匹配。不清楚为什么它不能工作。这确实是一个问题,伊根消失时,我使用的最新版本。
$ cat t21.cu
#include <thrust/iterator/zip_iterator.h>
#include <thrust/execution_policy.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>

#include <Eigen/Dense>
#include <iostream>

typedef thrust::device_vector<float>::iterator                     FloatIterator;
typedef thrust::tuple<FloatIterator, FloatIterator, FloatIterator> FloatIteratorTuple;
typedef thrust::zip_iterator<FloatIteratorTuple>                   Float3Iterator;

typedef thrust::tuple<float,float,float> Float3;

struct modify_tuple
{
    Eigen::Matrix4f _Mat4f;
    modify_tuple(Eigen::Matrix4f Mat4f) : _Mat4f(Mat4f) { }
    __host__ __device__ Float3 operator()(Float3 a) const
    {

        Eigen::Vector4f V(thrust::get<0>(a), thrust::get<1>(a), thrust::get<2>(a), 1.0);

    V=_Mat4f*V;

    Float3  res=thrust::make_tuple( V(0,0), V(1,0), V(2,0) );

        return res;
    }
};


int main(void)
{
    thrust::device_vector<float> X(3);
    thrust::device_vector<float> Y(3);
    thrust::device_vector<float> Z(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;

    std::cout << "X,Y,Z before transformation="<< std::endl;
    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;


    Float3Iterator P_first = thrust::make_zip_iterator(make_tuple(X.begin(), Y.begin(), Z.begin()));
    Float3Iterator P_last  = thrust::make_zip_iterator(make_tuple(X.end(),   Y.end(),   Z.end()));


    Eigen::Matrix4f M;
    M(0,0)= 1; M(0,1)= 2;  M(0,2)= 3;  M(0,3)= 4;
    M(1,0)= 5; M(1,1)= 6;  M(1,2)= 7;  M(1,3)= 8;
    M(2,0)= 9; M(2,1)= 10; M(2,2)= 11; M(2,3)= 12;
    M(3,0)= 13; M(3,1)= 14;  M(3,2)= 15;  M(3,3)= 16;

    thrust::transform(thrust::device, P_first,P_last, P_first, modify_tuple(M));

    std::cout << "X, Y, Z after transformation="<< std::endl;
    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;


    return 0;
}
$ nvcc -std=c++11 -I/path/to/eigen/eigen-eigen-71546f1a9f0c t21.cu -o t21 --expt-relaxed-constexpr
$ ./t21
X,Y,Z before transformation=
0,1,2,
4,5,6,
7,8,9,
X, Y, Z after transformation=
33,39,45,
81,99,117,
129,159,189,
$
$ cat t21.cu
#include <thrust/iterator/zip_iterator.h>
#include <thrust/execution_policy.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>

#include <Eigen/Dense>
#include <iostream>

typedef thrust::device_vector<float>::iterator                     FloatIterator;
typedef thrust::tuple<FloatIterator, FloatIterator, FloatIterator> FloatIteratorTuple;
typedef thrust::zip_iterator<FloatIteratorTuple>                   Float3Iterator;

typedef thrust::tuple<float,float,float> Float3;

struct modify_tuple
{
    Eigen::Matrix4f _Mat4f;
    modify_tuple(Eigen::Matrix4f Mat4f) : _Mat4f(Mat4f) { }
    __host__ __device__ Float3 operator()(Float3 a) const
    {

        Eigen::Vector4f V(thrust::get<0>(a), thrust::get<1>(a), thrust::get<2>(a), 1.0);

    V=_Mat4f*V;

    Float3  res=thrust::make_tuple( V(0,0), V(1,0), V(2,0) );

        return res;
    }
};


int main(void)
{
    thrust::device_vector<float> X(3);
    thrust::device_vector<float> Y(3);
    thrust::device_vector<float> Z(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;
    std::cout << "X,Y,Z before transformation="<< std::endl;
    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::host_vector<float> hX = X;
    thrust::host_vector<float> hY = Y;
    thrust::host_vector<float> hZ = Z;


    Float3Iterator P_first = thrust::make_zip_iterator(make_tuple(X.begin(), Y.begin(), Z.begin()));
    Float3Iterator P_last  = thrust::make_zip_iterator(make_tuple(X.end(),   Y.end(),   Z.end()));


    Eigen::Matrix4f M;
    M(0,0)= 1; M(0,1)= 2;  M(0,2)= 3;  M(0,3)= 4;
    M(1,0)= 5; M(1,1)= 6;  M(1,2)= 7;  M(1,3)= 8;
    M(2,0)= 9; M(2,1)= 10; M(2,2)= 11; M(2,3)= 12;
    M(3,0)= 13; M(3,1)= 14;  M(3,2)= 15;  M(3,3)= 16;

    thrust::transform(thrust::device, P_first,P_last, P_first, modify_tuple(M));

    std::cout << "X, Y, Z after transformation="<< std::endl;
    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;
    Eigen::Vector4f hV;
    hV(0) = hX[0];
    hV(1) = hY[0];
    hV(2) = hZ[0];
    hV(3) = 1;
    hV = M*hV;
    std::cout << "column 0:" << std::endl;
    std::cout << hV;
    std::cout << std::endl;
    hV(0) = hX[1];
    hV(1) = hY[1];
    hV(2) = hZ[1];
    hV(3) = 1;
    hV = M*hV;
    std::cout << "column 1:" << std::endl;
    std::cout << hV;
    std::cout << std::endl;
    hV(0) = hX[2];
    hV(1) = hY[2];
    hV(2) = hZ[2];
    hV(3) = 1;
    hV = M*hV;
    std::cout << "column 2:" << std::endl;
    std::cout << hV;
    std::cout << std::endl;

    return 0;
}
$ nvcc -std=c++11 -I/home/bob/eigen/eigen-eigen-71546f1a9f0c t21.cu -o t21 --expt-relaxed-constexpr
$ ./t21
X,Y,Z before transformation=
0,1,2,
4,5,6,
7,8,9,
X, Y, Z after transformation=
33,39,45,
81,99,117,
129,159,189,
column 0:
 33
 81
129
177
column 1:
 39
 99
159
219
column 2:
 45
117
189
261
$