提问人:nowox 提问时间:11/15/2023 更新时间:11/15/2023 访问量:86
在小型MCU上优化稀疏阵列中的元素查找
Optimizing Element Lookup in Sparse Array on small MCU
问:
我正在开发一个应用程序,该应用程序涉及管理分布在大小为 M 的数组中的 N 个 Element 实例,其中 N << M(N 比 M 小得多)。这些元素可以通过它们的索引进行访问,它们在数组中的分布在构建时是已知的,但没有遵循特定的模式。
主要目标:我寻求一种算法,该算法允许通过索引对元素进行有效(时间)检索,同时还要注意空间限制。理想情况下,我希望避免分配 O(M) 空间,这虽然会导致 O(1) 时间复杂度,但对于我的应用程序来说是不可行的。
上下文:此任务是为工作频率为 50 MHz 且没有浮点单元 (FPU) 的 16 位微控制器单元 (MCU) 开发 CanOpen 从站堆栈的一部分。传统的哈希表似乎是一个显而易见的解决方案,但由于 MCU 的局限性,它并不适合。
当前方法:我正在考虑使用简化的 Murmur 哈希函数的开放式寻址哈希表。下面是初步函数:
const int A = 16;
const int B = 0x45d9f3b;
const int C = B;
unsigned int hash(unsigned int x) {
x = ((x >> A) ^ x) * B;
x = ((x >> A) ^ x) * C;
x = (x >> A) ^ x;
return x;
}
我计划尝试使用不同的 A、B 和 C 值,以最大程度地减少访问时间并减少冲突。最终,使用自动化脚本运行构建时间以找到最佳的 A、B、C 常量。
问题:考虑到限制,这种方法是否可行,或者是否有更有效的算法或方法更适合这种情况?我对其他建议持开放态度,包括使用二叉搜索的可能性。
其他信息
此设置是运行实时应用程序的小型MCU上的CANopen从站堆栈的一部分。虽然 CanOpen 使用 16 位对象字典,但我的应用程序只需要 100-200 个对象。关键是尽量减少每个对象的访问时间。
我的处理能力有限,MCU 上没有 FPU。空间效率与时间效率同样重要。
答:
如果没有关于阵列结构的进一步信息,这是不可能的。
如果您有对象,则可以对数组进行编码。如果不发送那么多信号,就无法对所有可能的数组进行编码。这需要比特。这是数据。100
100^m
m * log_2(100)
O(m)
使用有关数组的其他数据,可以减少要编码的可能数组的数量,从而减少数据存储。但是,试图隐藏哈希函数背后的复杂性并不能使你摆脱鸽子洞原则——如果不使用足够的数据来创建不同的可能信号,你就无法区分不同的数组。这需要最少的位。x
x
log_2(x)
如果你能负担得起一个字节数组,我会这样做。否则,你要么会发现一些关于数组如何生成的东西,要么你将不得不将你的目标更改为可行的东西。m
考虑到这些限制,这种方法是否可行,或者是否有更有效的算法或方法更适合这种情况?
您描述的方法对于查找具有良好平均查找时间的哈希函数是可行的。
但我强烈建议使用您拥有的实际内存大小(但未在问题中指定)对碰撞概率进行一些简单的餐巾纸数学运算(为了简单起见,您可以假设哈希函数完美分布)来了解最坏情况。
你提到你有实时约束,所以我有一种感觉,最坏的情况时间(从碰撞链的最大长度得出)可能不让你满意。您可以让生成时脚本循环,直到它找到解决方案,但(取决于您的约束)可能并不总是有一个,因此在极少数情况下,您的生成可能会失败。
另一种方法是使用完美的哈希函数,它可以为您提供有保证的最坏情况,因为它没有冲突。
评论
O(m)
O(n)
O(m)
评论
O(n)