高效实现 64 位和 32 位无符号整数之间的双向映射
Efficient implementation of bidirectional map between 64bit and 32bit unsigned integers
想象一下我们有2台机器命名:Alice和Bob。Alice 支持 64 位无符号整数的操作,而 Bob 仅支持 32 位无符号整数的操作。
Bob 向 Alice 发送创建任务的请求。对于每个任务,Alice 分配唯一的 ID,该 ID 是随机的,但是唯一的 64 位无符号整数。Bob 最多可以创建 2^32 个任务。
我需要为 Bob 添加一项功能,以便能够按 ID 删除任务。因此,我需要设置一个代理,当消息从 Alice 发送到 Bob 时,它将用 32 位 uint 替换 64 位单元,并在消息向相反方向发送时从 32 位 uint 恢复 64 位 uint。
问题是我需要使转换非常高效,我只有~10MB的RAM来执行此操作。
是否有任何容器已经解决了这个问题?
更新
社区要求澄清,澄清的唯一方法是描述现实世界的情况。
因此,我正在研究作为AOSP一部分的OpenGL转换器库。总之,出于加速原因,它允许将Android系统的渲染(例如在VM内运行)移动到主机系统。
它是通过将所有OpenGL命令(来回)从目标(Android)流式传输到主机(即Win8 64位)来完成的。
OpenGL 对象表示为类型为GLuint
或unsigned 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 位机器之间的句柄转换无关。这是转换器的目标部分中的一个错误,它用错误的参数调用了错误的函数(glVertexAttribPointerData)。
根据最新核心OpenGL规范中的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
),并且每次调用只需生成一个唯一的索引。这会消耗更多内存,因为您还必须存储索引(它在数组中是imlicit),但如果0
是有效的上下文名称,则可以解决问题。
OpenGL 中的 uint 应该是 4 个字节,即宽度始终为 32 位,因此目标和主机上的句柄/名称都应该是 32 位
- 常量映射和常量元素映射之间的区别
- 如何在没有映射的情况下在枚举和字符串之间进行转换?
- C++11 在列表到映射(或其他容器)之间移动元素
- 在类之间传递映射
- 两个进程之间的共享映射内存在编辑时未更新
- 在 C++ 和 C# 之间共享内存映射文件结构
- 遍历std ::映射,效果少于迭代器之间的比较
- 本机C++类与 WinRT 组件(引用类)之间的自动映射
- 映射::擦除:按键擦除或迭代器擦除之间的区别
- 消除类似映射和类似矢量的容器之间的模板专用化
- 高效实现 64 位和 32 位无符号整数之间的双向映射
- 两个映射之间的分配-移动语义和性能
- 如何计算字符串到int的映射之间的所有排列
- Boost管理的映射文件:在OSX和Linux之间不兼容
- 将 1 到 12 之间的数字映射到月份名称
- 希望有效地克服 Boost.Process 间共享内存中映射中键类型之间的不匹配
- 映射和unorderd_map之间的 C 实现差异
- 计算表示稀疏向量 c++ 的映射之间的距离
- 如果没有for循环,我如何直接找到映射中指向两个不同键的任何两个迭代器之间的元素数量
- 整数集之间的映射