所以我有一个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
无论我按true
和UV1
的顺序,此函子都将返回UV2
。您的其他函子同样有缺陷。
在thrust speak中,这些不是有效的StrictWeakOrdering仿函数。如果要订购UV1
和UV2
,我们必须提供一个函子,该函子(一致地)对于一个演示文稿订单返回true
,对于另一个演示文稿订单返回false
。 (唯一的例外是,如果显示的两个数量确实相等,则函子应始终一致地仅返回一个答案,即true
或false
,而与显示顺序无关。但是UV1
和[C0对于您想要的排序,即相同结构的分组,此处给出的]不是“相等”。)
以下简单测试似乎对我有用:
UV2
[如果不清楚,这里没有专门针对推力和函子的使用;订购这些物品所用的基本逻辑必须正确才能有效排序。即使您编写了一个简单的串行冒泡排序,也必须使用类似的逻辑。函子中显示的逻辑不能用于提供合理的排序。
[如果您的方法还有其他问题,我不能说,因为您没有提供适当的$ 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也没有提供。