用推力对打包的顶点进行排序
Sorting packed vertices with thrust
所以我有一个 PackedVertex 结构的设备数组:
struct PackedVertex {
glm::vec3 Vertex;
glm::vec2 UV;
glm::vec3 Normal;
}
我正在尝试对它们进行排序,以便重复项在数组中聚集在一起;我根本不关心整体顺序。
我尝试通过比较 运行 向量的长度来对它们进行排序,但没有正确排序,所以现在我正在尝试使用 3 stable_sorts 和 binary_operators:
__thrust_hd_warning_disable__
struct sort_packed_verts_by_vertex : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.Vertex.x < rhs.Vertex.x || lhs.Vertex.y < rhs.Vertex.y || lhs.Vertex.z < rhs.Vertex.z;
}
};
__thrust_hd_warning_disable__
struct sort_packed_verts_by_uv : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.UV.x < rhs.UV.x || lhs.UV.y < rhs.UV.y;
}
};
__thrust_hd_warning_disable__
struct sort_packed_verts_by_normal : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.Normal.x < rhs.Normal.x || lhs.Normal.y < rhs.Normal.y || lhs.Normal.z < rhs.Normal.z;
}
};
问题是我现在遇到推力错误:"launch_closure_by_value" 这可能会导致猜测意味着我的排序由于我的运算符而没有收敛。
话虽这么说,但我也很确定这不是我进行此类排序的最佳方式,因此我们将不胜感激任何反馈。
我不相信你的排序函子是正确的。
排序仿函数必须给出一致的排序。让我们只考虑这个:
return lhs.UV.x < rhs.UV.x || lhs.UV.y < rhs.UV.y;
假设我有两个这样的 UV
数量:
UV1.x: 1
UV1.y: 0
UV2.x: 0
UV2.y: 1
无论我呈现 UV1
和 UV2
的顺序如何,这个函子都会 return true
。您的其他函子同样有缺陷。
在thrust speak, these are not valid StrictWeakOrdering 函子中。如果我们希望订购 UV1
和 UV2
,我们必须提供一个仿函数,它(一致地)returns true
用于一个呈现顺序,false
用于另一个演示顺序。 (唯一的例外是,如果两个呈现的数量确实相等,那么函子应该始终 return 只有一个答案,true
或 false
,始终如一,无论呈现顺序如何。但是,此处显示的 UV1
和 UV2
并非 "equal" 用于您所需的排序目的,即相同结构的分组。)
以下简单测试似乎对我有用:
$ cat t717.cu
#include <thrust/sort.h>
#include <thrust/device_ptr.h>
#include <iostream>
#include <stdlib.h>
#define DSIZE 64
#define RNG 10
struct PackedVertex {
float3 Vertex;
float2 UV;
float3 Normal;
};
struct my_PV_grouper {
template <typename T>
__host__ __device__
bool operator()(const T &lhs, const T &rhs) const {
if (lhs.Vertex.x > rhs.Vertex.x) return true;
else if (lhs.Vertex.x < rhs.Vertex.x) return false;
else if (lhs.Vertex.y > rhs.Vertex.y) return true;
else if (lhs.Vertex.y < rhs.Vertex.y) return false;
else if (lhs.Vertex.z > rhs.Vertex.z) return true;
else if (lhs.Vertex.z < rhs.Vertex.z) return false;
else if (lhs.UV.x > rhs.UV.x) return true;
else if (lhs.UV.x < rhs.UV.x) return false;
else if (lhs.UV.y > rhs.UV.y) return true;
else if (lhs.UV.y < rhs.UV.y) return false;
else if (lhs.Normal.x > rhs.Normal.x) return true;
else if (lhs.Normal.x < rhs.Normal.x) return false;
else if (lhs.Normal.y > rhs.Normal.y) return true;
else if (lhs.Normal.y < rhs.Normal.y) return false;
else if (lhs.Normal.z > rhs.Normal.z) return true;
else return false;
}
};
int main(){
PackedVertex h_data[DSIZE];
PackedVertex *d_data;
for (int i =0; i < DSIZE; i++)
h_data[i].Vertex.x = h_data[i].Vertex.y = h_data[i].Vertex.z = h_data[i].UV.x = h_data[i].UV.y = h_data[i].Normal.x = h_data[i].Normal.y = h_data[i].Normal.z = rand()%RNG;
cudaMalloc(&d_data, DSIZE*sizeof(PackedVertex));
cudaMemcpy(d_data, h_data, DSIZE*sizeof(PackedVertex), cudaMemcpyHostToDevice);
thrust::device_ptr<PackedVertex> d_ptr(d_data);
thrust::sort(d_ptr, d_ptr+DSIZE, my_PV_grouper());
cudaMemcpy(h_data, d_data, DSIZE*sizeof(PackedVertex), cudaMemcpyDeviceToHost);
for (int i =0; i < DSIZE; i++)
std::cout << h_data[i].Vertex.x << " ";
std::cout << std::endl;
}
$ nvcc -o t717 t717.cu
$ ./t717
9 9 9 9 9 9 9 8 8 8 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 5 5 5 5 5 5 4 4 4 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0
$
如果不清楚,这里没有特别说明推力和函子的用法;用于排序这些项目的基本逻辑需要正确才能进行有效排序。即使您编写了一个简单的串行冒泡排序,也必须使用类似的逻辑。您的函子中呈现的逻辑不能用于提供合理的排序。
如果您的方法还有其他问题,我不能说,因为您没有为此类问题提供适当的 MCVE, which is expected。
所以我有一个 PackedVertex 结构的设备数组:
struct PackedVertex {
glm::vec3 Vertex;
glm::vec2 UV;
glm::vec3 Normal;
}
我正在尝试对它们进行排序,以便重复项在数组中聚集在一起;我根本不关心整体顺序。
我尝试通过比较 运行 向量的长度来对它们进行排序,但没有正确排序,所以现在我正在尝试使用 3 stable_sorts 和 binary_operators:
__thrust_hd_warning_disable__
struct sort_packed_verts_by_vertex : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.Vertex.x < rhs.Vertex.x || lhs.Vertex.y < rhs.Vertex.y || lhs.Vertex.z < rhs.Vertex.z;
}
};
__thrust_hd_warning_disable__
struct sort_packed_verts_by_uv : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.UV.x < rhs.UV.x || lhs.UV.y < rhs.UV.y;
}
};
__thrust_hd_warning_disable__
struct sort_packed_verts_by_normal : public thrust::binary_function < PackedVertex, PackedVertex, bool >
{
__host__ __device__ bool operator()(const PackedVertex &lhs, const PackedVertex &rhs)
{
return lhs.Normal.x < rhs.Normal.x || lhs.Normal.y < rhs.Normal.y || lhs.Normal.z < rhs.Normal.z;
}
};
问题是我现在遇到推力错误:"launch_closure_by_value" 这可能会导致猜测意味着我的排序由于我的运算符而没有收敛。
话虽这么说,但我也很确定这不是我进行此类排序的最佳方式,因此我们将不胜感激任何反馈。
我不相信你的排序函子是正确的。
排序仿函数必须给出一致的排序。让我们只考虑这个:
return lhs.UV.x < rhs.UV.x || lhs.UV.y < rhs.UV.y;
假设我有两个这样的 UV
数量:
UV1.x: 1
UV1.y: 0
UV2.x: 0
UV2.y: 1
无论我呈现 UV1
和 UV2
的顺序如何,这个函子都会 return true
。您的其他函子同样有缺陷。
在thrust speak, these are not valid StrictWeakOrdering 函子中。如果我们希望订购 UV1
和 UV2
,我们必须提供一个仿函数,它(一致地)returns true
用于一个呈现顺序,false
用于另一个演示顺序。 (唯一的例外是,如果两个呈现的数量确实相等,那么函子应该始终 return 只有一个答案,true
或 false
,始终如一,无论呈现顺序如何。但是,此处显示的 UV1
和 UV2
并非 "equal" 用于您所需的排序目的,即相同结构的分组。)
以下简单测试似乎对我有用:
$ cat t717.cu
#include <thrust/sort.h>
#include <thrust/device_ptr.h>
#include <iostream>
#include <stdlib.h>
#define DSIZE 64
#define RNG 10
struct PackedVertex {
float3 Vertex;
float2 UV;
float3 Normal;
};
struct my_PV_grouper {
template <typename T>
__host__ __device__
bool operator()(const T &lhs, const T &rhs) const {
if (lhs.Vertex.x > rhs.Vertex.x) return true;
else if (lhs.Vertex.x < rhs.Vertex.x) return false;
else if (lhs.Vertex.y > rhs.Vertex.y) return true;
else if (lhs.Vertex.y < rhs.Vertex.y) return false;
else if (lhs.Vertex.z > rhs.Vertex.z) return true;
else if (lhs.Vertex.z < rhs.Vertex.z) return false;
else if (lhs.UV.x > rhs.UV.x) return true;
else if (lhs.UV.x < rhs.UV.x) return false;
else if (lhs.UV.y > rhs.UV.y) return true;
else if (lhs.UV.y < rhs.UV.y) return false;
else if (lhs.Normal.x > rhs.Normal.x) return true;
else if (lhs.Normal.x < rhs.Normal.x) return false;
else if (lhs.Normal.y > rhs.Normal.y) return true;
else if (lhs.Normal.y < rhs.Normal.y) return false;
else if (lhs.Normal.z > rhs.Normal.z) return true;
else return false;
}
};
int main(){
PackedVertex h_data[DSIZE];
PackedVertex *d_data;
for (int i =0; i < DSIZE; i++)
h_data[i].Vertex.x = h_data[i].Vertex.y = h_data[i].Vertex.z = h_data[i].UV.x = h_data[i].UV.y = h_data[i].Normal.x = h_data[i].Normal.y = h_data[i].Normal.z = rand()%RNG;
cudaMalloc(&d_data, DSIZE*sizeof(PackedVertex));
cudaMemcpy(d_data, h_data, DSIZE*sizeof(PackedVertex), cudaMemcpyHostToDevice);
thrust::device_ptr<PackedVertex> d_ptr(d_data);
thrust::sort(d_ptr, d_ptr+DSIZE, my_PV_grouper());
cudaMemcpy(h_data, d_data, DSIZE*sizeof(PackedVertex), cudaMemcpyDeviceToHost);
for (int i =0; i < DSIZE; i++)
std::cout << h_data[i].Vertex.x << " ";
std::cout << std::endl;
}
$ nvcc -o t717 t717.cu
$ ./t717
9 9 9 9 9 9 9 8 8 8 7 7 7 7 7 7 7 6 6 6 6 6 6 6 6 6 5 5 5 5 5 5 4 4 4 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 0 0 0 0 0 0
$
如果不清楚,这里没有特别说明推力和函子的用法;用于排序这些项目的基本逻辑需要正确才能进行有效排序。即使您编写了一个简单的串行冒泡排序,也必须使用类似的逻辑。您的函子中呈现的逻辑不能用于提供合理的排序。
如果您的方法还有其他问题,我不能说,因为您没有为此类问题提供适当的 MCVE, which is expected。