CUDA - 将 float3 数组的 (x,y,z) 分量分开 min/max?
CUDA - Separate min/max of (x,y,z) components of float3 array?
我在 CUDA 设备上有一个 float3 点数组。我想快速找到 x、y 和 z 分量的最小值和最大值(分别)。
我知道已经存在大量使用缩减算法查找数组 min/max 值的实现,但我找不到任何对多分量变量执行相同操作或提供的实现提供步幅的选项。
有谁知道可以执行此操作的任何现有实现吗?
我想出了一个使用推力和自定义比较器的方法,
对于希望做类似事情的任何人,您可以执行以下操作。在我的机器上,对于大于 1000 万个元素的数据集,性能提高了 10 倍以上:
// Comparators
struct comp_float3_x{
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs){
return lhs.x < rhs.x;
}
};
struct comp_float3_y {
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs) {
return lhs.y < rhs.y;
}
};
struct comp_float3_z {
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs) {
return lhs.z < rhs.z;
}
};
void getMinMaxDeviceFloat3(Vec3i& min, Vec3i& max, const DeviceArray<float3>& points)
{
// Thrust does not deal with raw pointers well, wrapping is necessary
thrust::device_ptr<float3> ptr = thrust::device_pointer_cast(points.ptr());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_x = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_x());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_y = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_y());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_z = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_z());
// Host buffers
float3 min_x_host, min_y_host, min_z_host, max_x_host, max_y_host, max_z_host;
// Copy data to host
cudaMemcpy(&min_x_host, minmax_x.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&min_y_host, minmax_y.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&min_z_host, minmax_z.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_x_host, minmax_x.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_y_host, minmax_y.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_z_host, minmax_z.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
// Assign output
min[0] = (int)min_x_host.x;
min[1] = (int)min_y_host.y;
min[2] = (int)min_z_host.z;
max[0] = (int)max_x_host.x;
max[1] = (int)max_y_host.y;
max[2] = (int)max_z_host.z;
}
我在 CUDA 设备上有一个 float3 点数组。我想快速找到 x、y 和 z 分量的最小值和最大值(分别)。
我知道已经存在大量使用缩减算法查找数组 min/max 值的实现,但我找不到任何对多分量变量执行相同操作或提供的实现提供步幅的选项。
有谁知道可以执行此操作的任何现有实现吗?
我想出了一个使用推力和自定义比较器的方法,
对于希望做类似事情的任何人,您可以执行以下操作。在我的机器上,对于大于 1000 万个元素的数据集,性能提高了 10 倍以上:
// Comparators
struct comp_float3_x{
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs){
return lhs.x < rhs.x;
}
};
struct comp_float3_y {
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs) {
return lhs.y < rhs.y;
}
};
struct comp_float3_z {
__host__ __device__
bool operator()(const float3& lhs, const float3& rhs) {
return lhs.z < rhs.z;
}
};
void getMinMaxDeviceFloat3(Vec3i& min, Vec3i& max, const DeviceArray<float3>& points)
{
// Thrust does not deal with raw pointers well, wrapping is necessary
thrust::device_ptr<float3> ptr = thrust::device_pointer_cast(points.ptr());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_x = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_x());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_y = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_y());
thrust::pair<thrust::device_ptr<float3>, thrust::device_ptr<float3>> minmax_z = thrust::minmax_element(thrust::device, ptr, ptr + occupied_voxels, comp_float3_z());
// Host buffers
float3 min_x_host, min_y_host, min_z_host, max_x_host, max_y_host, max_z_host;
// Copy data to host
cudaMemcpy(&min_x_host, minmax_x.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&min_y_host, minmax_y.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&min_z_host, minmax_z.first.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_x_host, minmax_x.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_y_host, minmax_y.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
cudaMemcpy(&max_z_host, minmax_z.second.get(), sizeof(float3), cudaMemcpyDeviceToHost);
// Assign output
min[0] = (int)min_x_host.x;
min[1] = (int)min_y_host.y;
min[2] = (int)min_z_host.z;
max[0] = (int)max_x_host.x;
max[1] = (int)max_y_host.y;
max[2] = (int)max_z_host.z;
}