按推力排列堆积顶点

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

所以我有一个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”,这会造成猜测,这意味着我的排序因操作员而未收敛。

话虽这么说,我也很确定这不是我做这种类型的最佳方法,所以任何反馈将不胜感激。

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

我不相信您的排序函子是正确的。

排序函子必须给出一致的顺序。让我们考虑一下这个:

    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

无论我按trueUV1的顺序,此函子都将返回UV2。您的其他函子同样有缺陷。

thrust speak中,这些不是有效的StrictWeakOrdering仿函数。如果要订购UV1UV2,我们必须提供一个函子,该函子(一致地)对于一个演示文稿订单返回true,对于另一个演示文稿订单返回false。 (唯一的例外是,如果显示的两个数量确实相等,则函子应始终一致地仅返回一个答案,即truefalse,而与显示顺序无关。但是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也没有提供。

© www.soinside.com 2019 - 2024. All rights reserved.