推力::变换输出的值错误

问题描述 投票:-2回答:1

我正在尝试通过使用容器将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时,我得到的值确实很奇怪,与我的输出必须没有任何关系。我怀疑我没有正确初始化输出主机/设备向量。我尝试了其他方法来初始化它们,但是它们在编译时都会给我错误。我不确定自己在做什么错。

c++ cuda thrust
1个回答
1
投票

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

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

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)将在设备和主机上都定义一个默认的构造函数,在每个类实例的初始化期间容器必须调用该构造函数。

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

$ 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
© www.soinside.com 2019 - 2024. All rights reserved.