SSBO hash table, missing values

有些话、适合烂在心里 提交于 2020-01-15 09:24:26

问题


I am trying to run a little data compression experiment. I am trying to compress 3D textures into hash tables to avoid storing empty volume information.

To this effect I wrote the hashing function and retreiving function (they are in different shaders):

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;
    }
}

My current issue however is that I am missing about 90% of the voxel values:

The intended result is:

I have had some ideas as to what could be wrong but none seem to be it:

  • Number of hashes is bigger than array size. I allocated 100 000 000 bytes, the total size of the voxel structure should be 4*4*3 = 48, giving me a total possible element number of 2 083 333.33. I capped the array size at a million, which is half of that, so I shouldn't be accessing unallocated memory.

  • Hash function collides more than 50 times, causing most of the elements to be discarded. I could be wrong, but I am using quadratic updating to increase the hashed index, this should be better than linear. And I am also relying on the FTA to guarantee unique key generation before digesting. So I am skeptic that so many hashes collide more than 50 times. Moreover, the fact that the voxels that were kept are all in such a nice region (a liner diagonal slice) doesn't seem to match this hypothesis. If it was a collision problem I should be seeing a semi uniform distribution of wholes, not such a nicely defined region.

  • Driver can't allocate that much vram for the ssbo. I am using a GTX 1070 with the latest NVIDIA drivers, the documentation says that the spec guarantees a minimum size of 128 MB but that most implementations let you allocate up to the total memory size. I allocated 100 000 000 bytes, which is under the upper limit, and even if the driver aligns my memory to 128 MB it should not affect the result of my computations since i keep track of the logical array size myself.

Any ideas as to why I am loosing so much information when compressing?

EDIT: Added atomic operations based on a comment

EDIT 2: Solution was found in a comment, result:

Some memory loss still happens, but that was expected.


回答1:


Your hash function

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

is very poor. Since discretized is an ivec3, the whole operation is working on integers, and the term pow(2, discretized.y) will be 0 for whenever discretized.y is >= 31, resulting in your complete hash value to evaluate to 0. Also, for discretized.y < 0, you should get 0, as the resulting fractions are also not representable by int types. Furthermore, your quadratic probing also fails for index == 0, since you will probe 50 times the same index.



来源:https://stackoverflow.com/questions/54280066/ssbo-hash-table-missing-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!