繁体   English   中英

推力值错误::transform output

[英]Wrong values of thrust::transform output

我正在尝试通过使用容器将float3数组转换为特定结构的容器。 下面的代码:

#include <thrust/device_ptr.h>
#include <thrust/extrema.h>
#include <thrust/reduce.h>
#include <thrust/execution_policy.h>
#include <thrust/functional.h>

// Ouput structure for thrust::transform
struct cloud_point_index_idx {
  unsigned int idx;
  float3 cloud_point;

  cloud_point_index_idx(unsigned int idx_, float3 cloud_point_) :
    idx(idx_), cloud_point(cloud_point_) {}

  bool operator < (const cloud_point_index_idx &p) const {
    return (idx < p.idx);
  }
};
// Functor for thrust::transform
struct point2voxelcentroid {
  float3 leaf_size;
  int min_x, min_y, min_z;

  point2voxelcentroid(float3 leaf_size,int min_x, int min_y, int min_z) {
    this->leaf_size = leaf_size;
    this->min_x = min_x; this->min_y = min_y; this->min_z = min_z;
  }

  __host__ __device__
  cloud_point_index_idx operator()(const float3 point) const {
    int ijk0 = static_cast<int>(floor(point.x / leaf_size.x) -
      static_cast<float>(min_x));
    int ijk1 = static_cast<int>(floor(point.y / leaf_size.y) -
      static_cast<float>(min_y));
    int ijk2 = static_cast<int>(floor(point.z / leaf_size.z) -
      static_cast<float>(min_z));

    int voxel_idx = ijk0 + ijk1 + ijk2;
    return cloud_point_index_idx(static_cast<unsigned int>(voxel_idx), point);
  }
};

int main() { // Example
  int num_points = 5;
  float3 data[5] = {{1, 0, 2}, {2, 1, 3}, {1, 1, -5}, {-1, 3, -2}, {-5, -2, 0}}; // Set the data
  int min_b_[3] = {-5, -2, -5};
  float3 leaf_size = {0.5, 0.5, 0.5};
  thrust::device_vector<float3> d_ptr(data, data + num_points); // Wrap it into a device_vector
  thrust::device_vector<cloud_point_index_idx> voxel_idx_vector; // Output
  voxel_idx_vector.reserve(num_points);
  thrust::transform(
    thrust::device,
    d_ptr.begin(), d_ptr.end(),
    voxel_idx_vector.begin(),
    point2voxelcentroid(leaf_size, min_b_[0], min_b_[1], min_b_[2]));

  thrust::host_vector<cloud_point_index_idx> indices; // Host vector to verify
  indices.reserve(num_points);
  thrust::copy(voxel_idx_vector.begin(), voxel_idx_vector.end(), indices.begin()); // Copy device to host

  // Print out values
  std::cout << "\n---\nAfter assignment\n";
  for (int i = 0; i < num_points; i++) {
    std::cout << "Voxel idx: " << indices[i].idx << ". Point: [" << indices[i].cloud_point.x << ", "
       << indices[i].cloud_point.y << ", " << indices[i].cloud_point.z << std::endl;
  }
}

我检查了我的仿函数值,它们似乎正确解析了数据,但是当我打印我的 host_vector 时,我得到了非常奇怪的值,与我的 output 必须是什么无关。 我怀疑我没有正确初始化我的 output 主机/设备向量。 我尝试了其他方法来初始化它们,但它们在编译时都会给我错误。 我不确定我做错了什么。

这里有几个问题,但最严重的是使用reserve ,它实际上并没有为推力容器分配 memory。

您需要做的是定义一个默认构造函数并在实例化时显式分配一个大小。 像这样的东西:

struct cloud_point_index_idx {
  int idx;
  float3 cloud_point;

  cloud_point_index_idx()=default;

  __host__ __device__
  cloud_point_index_idx(unsigned int idx_, float3 cloud_point_) :
    idx(idx_), cloud_point(cloud_point_) {}

  __host__ __device__
  bool operator < (const cloud_point_index_idx &p) const {
    return (idx < p.idx);
  }
};

(需要-std=c++11 )将在设备和主机上定义一个默认构造函数,容器必须在每个 class 实例的初始化期间调用该构造函数。

您的代码的这种修改对我有用:

$ cat bodgey.cu

#include <thrust/device_vector.h>
#include <thrust/device_ptr.h>
#include <thrust/extrema.h>
#include <thrust/reduce.h>
#include <thrust/execution_policy.h>
#include <thrust/functional.h>

#include <iostream>

// Ouput structure for thrust::transform
struct cloud_point_index_idx {
  int idx;
  float3 cloud_point;

  cloud_point_index_idx()=default;

  __host__ __device__
  cloud_point_index_idx(unsigned int idx_, float3 cloud_point_) :
    idx(idx_), cloud_point(cloud_point_) {}

  __host__ __device__
  bool operator < (const cloud_point_index_idx &p) const {
    return (idx < p.idx);
  }
};
// Functor for thrust::transform
struct point2voxelcentroid {
  float3 leaf_size;
  int min_x, min_y, min_z;

  point2voxelcentroid(float3 leaf_size,int min_x, int min_y, int min_z) {
    this->leaf_size = leaf_size;
    this->min_x = min_x; this->min_y = min_y; this->min_z = min_z;
  }

  __host__ __device__
  cloud_point_index_idx operator()(const float3 point) const {
    int ijk0 = static_cast<int>(floor(point.x / leaf_size.x) -
      static_cast<float>(min_x));
    int ijk1 = static_cast<int>(floor(point.y / leaf_size.y) -
      static_cast<float>(min_y));
    int ijk2 = static_cast<int>(floor(point.z / leaf_size.z) -
      static_cast<float>(min_z));

    int voxel_idx = ijk0 + ijk1 + ijk2;
    return cloud_point_index_idx(voxel_idx, point);
  }
};

int main() { // Example
  int num_points = 5;
  float3 data[5] = {{1, 0, 2}, {2, 1, 3}, {1, 1, -5}, {-1, 3, -2}, {-5, -2, 0}}; // Set the data
  int min_b_[3] = {-5, -2, -5};
  float3 leaf_size = {0.5, 0.5, 0.5};
  thrust::device_vector<float3> d_ptr(data, data + num_points); // Wrap it into a device_vector
  thrust::device_vector<cloud_point_index_idx> voxel_idx_vector(num_points); // Output
  thrust::transform(
    thrust::device,
    d_ptr.begin(), d_ptr.end(),
    voxel_idx_vector.begin(),
    point2voxelcentroid(leaf_size, min_b_[0], min_b_[1], min_b_[2]));

  thrust::host_vector<cloud_point_index_idx> indices(num_points); // Host vector to verify
  thrust::copy(voxel_idx_vector.begin(), voxel_idx_vector.end(), indices.begin()); // Copy device to host

  // Print out values
  std::cout << "\n---\nAfter assignment\n";
  for (int i = 0; i < num_points; i++) {
    std::cout << "Voxel idx: " << indices[i].idx << ". Point: [" << indices[i].cloud_point.x << ", "
       << indices[i].cloud_point.y << ", " << indices[i].cloud_point.z << std::endl;
  }
}

$ nvcc -std=c++11 -arch=sm_52 -o bodgey bodgey.cu 

$ ./bodgey 

---
After assignment
Voxel idx: 18. Point: [1, 0, 2
Voxel idx: 24. Point: [2, 1, 3
Voxel idx: 6. Point: [1, 1, -5
Voxel idx: 12. Point: [-1, 3, -2
Voxel idx: -2. Point: [-5, -2, 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM