使用推力对打包顶点进行排序 [英] Sorting packed vertices with thrust

查看:96
本文介绍了使用推力对打包顶点进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我有一个PackedVertex结构的设备数组:

So I have an device array of PackedVertex structs:

struct PackedVertex {
  glm::vec3 Vertex;
  glm::vec2 UV;
  glm::vec3 Normal;
}

所述重复在所述阵列中聚集在一起;我根本不在乎整体顺序。

I'm trying to sort them so that duplicates are clustered together in the array; I don't care about overall order at all.

我试过通过比较向量的长度进行排序,但没有正确排序,所以现在我尝试每个变量使用3 stable_sorts与binary_operators:

I've tried sorting them by comparing the lengths of the vectors which ran but didn't sort them correctly so now I'm trying per variable using 3 stable_sorts with the 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,危害一个猜测意味着排序不是由于我的操作符收敛。

Trouble is I'm getting a thrust error now: "launch_closure_by_value" which hazarding a guess means that my sort isn't converging due to my operators.

这是说我也很肯定这不是我做这种排序的最好方法

That being said I'm also pretty sure this is not the best way for me to be doing this kind of sort so any feedback would be greatly appreciated.

推荐答案

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

I don't believe your sort functors are correct.

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

A sort functor must give a consistent ordering. Let's just consider this one:

    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 。你的其他同事也有同样的缺陷。

This functor will return true no matter which order I present UV1 and UV2. Your other functors are similarly defective.

推动说话,这些 StrictWeakOrdering 函数无效。如果我们想订购 UV1 UV2 ,我们必须提供一个函数> true 用于一个显示顺序, false 用于其他显示顺序。 (唯一的例外是,如果两个呈现的量真的相等,那么函子总是返回一个答案, true false ,不管显示顺序如何,但是这里给出的 UV1 UV2 等于)。

In thrust speak, these are not valid StrictWeakOrdering functors. If we wish to order UV1 and UV2, we must provide a functor which (consistently) returns true for one presentation order and false for the other presentation order. (The only exception to this is if the two presented quantities are truly equal, then the functor should always return just one answer, either true or false, consistently, regardless of presentation order. However the UV1 and UV2 presented here are not "equal" for the purposes of your desired ordering, i.e. grouping of identical structs.)

以下简单的测试似乎对我有用:

The following simple test seems to work for me:

$ 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
$

如果不清楚,在这里没有什么特别的特定的推力和函数的使用;用于订购这些项目的基本逻辑需要对于有效排序是正确的。即使你写了一个简单的串行冒泡排序,它将不得不使用类似的逻辑。

In case it's not clear, there is nothing particularly specific to the usage of thrust and functors here; the fundamental logic used to order these items needs to be correct for a valid sort. Even if you wrote a simple serial bubble-sort, it would have to use similar logic. The logic presented in your functors cannot be used to provide a sensible ordering.

如果您的方法还有其他问题,我不能说,因为您没有提供适当的 MCVE 预期来查询这样的问题。

If there are other problems with your approach, I can't say, as you have not provided a proper MCVE, which is expected for questions like this.

这篇关于使用推力对打包顶点进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆