SSBO哈希表,缺少值

时间:2019-01-20 19:19:30

标签: c++ opengl hash graphics glsl

我正在尝试进行一些数据压缩实验。我正在尝试将3D纹理压缩到哈希表中,以避免存储空的卷信息。

为此,我编写了哈希函数和检索函数(它们在不同的着色器中):

struct Voxel
{
    int filled;
    ivec4 position;
    vec4 normal;
    vec4 color;
};

layout(std430, binding = 0) buffer voxel_buffer
{
    uint index;
    Voxel voxels[];
};
// Data storing shader
int a_size = 10000000;
void insert(vec3 pos, Voxel value) {
    ivec3 discretized = ivec3(pos / v_size);
    int index = int(pow(7, discretized.x) * pow(2, discretized.y) * pow(3, discretized.z)) % a_size;

    for(int i=0; i<50; i++) {
        if(atomicCompSwap(voxels[index].filled, 0, 1) == 0) {
           Voxel c_voxel = voxels[index];
           value.position = ivec4(discretized, 1);
           voxels[index] = value;
           break;
         }

        index = (index * index) % a_size;
    }
}
//Data reading shader
int a_size = 10000000;
vec4 fetch(vec3 pos) {
    ivec3 discretized = ivec3(pos / v_size);
    int index = int(pow(7, discretized.x) * pow(2, discretized.y) * pow(3, discretized.z)) % a_size;

    for(int i=0; i<50; i++) {
        Voxel c_voxel = voxels[index];

        if(ivec4(discretized,1) == voxels[index].position)
            return voxels[index].color;

        index = (index * index) % a_size;
    }
}

但是我当前的问题是我缺少大约90%的体素值:

Population

预期结果是:

enter image description here

我对可能出什么问题有一些想法,但似乎没有:

  • 哈希数大于数组大小。我分配了1亿个字节,体素结构的总大小应为4 * 4 * 3 = 48,这使我可以使用的元素总数为2 083 333.33。我将数组的大小限制为一百万,是数组大小的一半,所以我不应该访问未分配的内存。

  • 哈希函数碰撞50次以上,导致大多数元素被丢弃。我可能是错的,但是我使用二次更新来增加哈希索引,这应该比线性更好。而且我也依靠FTA来确保在消化之前唯一的密钥生成。因此,我怀疑如此多的哈希冲突超过50次。此外,保留的体素都在一个很好的区域(线性对角线切片) 似乎与这个假设不符。如果这是一个碰撞问题,我应该看到整体的半均匀分布,而不是这样定义的区域。

  • 驱动程序无法为ssbo分配那么多的vram。我使用的是带有最新NVIDIA驱动程序的GTX 1070,该文档说该规范保证最小大小为128 MB,但大多数实现都允许您分配总内存大小。我分配了1亿个字节,这是上限,并且即使驱动程序将我的内存对齐为128 MB,也不会影响我的计算结果,因为我自己会跟踪逻辑数组的大小。

    < / li>

关于压缩时为什么丢失这么多信息的任何想法吗?

编辑: 根据评论添加了原子操作

编辑2: 在评论中找到了解决方案,结果: enter image description here

仍然会发生一些内存丢失,但这是预期的。

1 个答案:

答案 0 :(得分:2)

您的哈希函数

int(pow(7, discretized.x) * pow(2, discretized.y) * pow(3, discretized.z)) % a_size;

非常差。由于discretizedivec3,因此整个操作都在整数上进行,并且无论何时pow(2, discretized.y)0时,术语discretized.y将是>= 31。 ,得出完整的哈希值以评估为0。另外,对于discretized.y < 0,您应该得到0,因为结果分数也不能用int类型表示。此外,index == 0的二次探测也会失败,因为您将探测相同索引的50倍。