在64位和32位无符号整数之间有效实现双向映射

时间:2014-01-27 17:06:23

标签: c++ c algorithm opengl containers

想象一下,我们有2台名为Alice和Bob的机器。 Alice支持64位无符号整数的操作,而Bob仅支持32位无符号整数。

Bob发送Alice请求以创建任务。对于每个任务,Alice分配唯一ID,该ID是随机但唯一的64位无符号整数。 Bob最多可以创建2 ^ 32个任务。

我需要为Bob添加一项能够按ID删除任务的功能。因此,当消息从Alice转发到Bob时,我需要设置一个代替64位单位的代理,当消息反向时,从32位uint恢复64位uint。

问题在于我需要使转换效率非常高,我只需要大约10MB的RAM来实现这一目标 是否有任何容器已经解决了这个问题?

更新

社区要求澄清,澄清它的唯一方法是描述现实世界的情况。

所以,我正在研究属于AOSP的OpenGL翻译库。总之,出于加速原因,它允许将Android系统的渲染(例如,在VM内部运行)移动到主机系统 它是通过将所有OpenGL命令(前后)从Target(Android)流式传输到主机(即Win8 64bit)来完成的。

OpenGL对象表示为GLuintunsigned int类型的句柄。因此,对象的大小和允许的值取决于系统是32位还是64位。

由于大多数Android系统是32位且大多数主机系统是64位,因此出现了问题:在从Android创建OpenGL对象的请求中,主机可以创建具有不能表示为32位值的值的句柄。但是,由于显而易见的原因,Android不能要求超过2^32 - 1个对象。

我想到的唯一解决方案是设置将64位句柄映射到32位的代理,反之亦然。

产生问题的具体代码:https://android.googlesource.com/platform/sdk/+/master/emulator/opengl/host/libs/Translator/include/GLcommon/GLutils.h第47行。

更新2

在进一步探讨问题之后,我发现这不是GLuint的问题(如@KillianDS所述)。然而,它仍然是OpenGL的问题。

有些函数返回指针,而不是GLuint句柄。例如。 eglCreateContext。 我需要找到一种在64位主机和32位目标之间交换指针的方法。

更新3

最后我发现这个具体的崩溃与32位和64位机器之间的句柄转换无关。翻译器的Target部分中的一个错误是使用错误的参数调用错误的函数(glVertexAttribPointerData)。

2 个答案:

答案 0 :(得分:2)

根据latest core OpenGL spec中的table 2.2,OpenGL中的uint应始终为32位宽(ES的规格大致相同)。据我所知,所有OpenGL名称/句柄都是uint的。因此,它在主机和目标上都应该是32位。

请注意,正是因为unsigned int的实际位宽在OpenGL具有应符合规范的类型的平台之间可能会有所不同。

更新

如果剩下的句柄实际上只是上下文和其他窗口系统调用,我会保持简单,因为我们不是在谈论频繁的操作,也不是大量的句柄。每个GPU的每个OpenGL应用程序通常不会执行这些操作,这在任何移动电话上都可能是1。我认为最简单的解决方案是使用数组。伪代码

class context_creator
{
    std::array<EGLContext, 1000> context_map; //8KB
public:
    context_creator() : context_map{} {}
    uint32_t allocate(...) {
        for(unsigned i = 0; i < context_map.size(); i++) {
            if(!context_map[i]) {
                context_map[i] = eglCreateContext(...);
                return i;
            }
        }
    }
    void deallocate(uint32_t handle) {
        eglDeleteContext(context_map[handle]);
        context_map[handle] = 0;
    }
    //Has to be called in every function where a context is a parameter.
    EGLContext translate(uint32_t handle) const {
        return context_map[handle];
    }
}

请注意,如果0是上下文的有效名称,则无效。我真的不知道WGL,但可能不是。这样做的好处是虽然分配不是有史以来最快的算法,但是翻译是O(1),而且最常见的是最常见的。

当然,存在变化:

  • 您可以使用更具动态性的容器(例如vector)而不是固定大小。
  • 您可以使用哈希表(如std::map),只需为每次调用生成唯一索引。这也消耗了更多的内存,因为你必须存储索引(它在数组中是隐式的),但如果0是一个有效的上下文名称,它就解决了这个问题。

答案 1 :(得分:-1)

OpenGL中的uint应为4个字节,即32位始终为宽度,因此目标和主机上的句柄/名称应为32位