为提高性能而增加可忽略的错误风险是否可以? (固定哈希映射桶大小)

Is it OK to to add negligible risks of errors for performance gains? (fixed hash map bucket size)

我最近一直在为 C 中的项目制作自定义哈希映射。

我的哈希映射目前是这样工作的:

我目前使用此哈希映射的一个问题是创建它对于我的用例来说太慢了(我必须创建很多,在数百万范围内)。

提高创建速度的一个简单解决方案是只在需要时分配存储桶,但这实际上只会延迟分配,而且性能提升微乎其微。

我想到的一个想法是每个存储桶只有一个 fixed-size 项目数组。这样一来,如果做得好,我只需要为每个地图分配一个大的堆。但是,桶数组存在 non-resolvable 溢出的轻微风险,尤其是在尺寸较小的情况下。我有 calculated,从 32 个桶和 18 个项目的固定容量开始,概率大约为 10^(-19)(如果我的数学是正确的),并且随着桶的增加,它会变得更小。因此,发生该错误的可能性基本上可以忽略不计。

特别是本着 data-oriented 设计的精神,我发现哈希映射的这个概念非常有趣,但我找不到任何关于忽略可忽略的错误风险是否是一种编程实践可以, 是或什至应该被使用。我真的很想知道这是否是任何地方的已知做法,是否可以在散列映射之外的其他地方找到它。

一如既往,答案是“视情况而定”。以最普遍的方式思考这个问题,肯定存在真实的神圣用例,其中为了性能而故意不正确的结果(想想分布式系统,eventual consistency 作为一个例子)。然而,对于任何使用此类系统的严肃系统,都有对权衡的深入分析(数学证明、市场分析等)以及对权衡的充分理解和接受。

回到你的例子。为了简单起见,让我们稍微改变一下问题。假设发生错误时,用户会收到一条错误消息,并且用户可以轻松地重新启动应用程序。这似乎相当合理。但这是愿意为性能优势做出的可接受的权衡吗?只有你能回答。

现在你的真实用例是混乱的,因为当数组溢出时你的程序有未定义的行为。您无法知道程序将如何运行。您甚至不知道程序何时出错以及是否出错。任何事情都可能发生。该程序可能看起来正常,可能会崩溃,可能会开始给出奇怪的结果,实际上是任何事情。这是一个可以接受的权衡吗?再一次,只有你能回答。

但我的两分钱是你应该首先瞄准 正确的 程序。未定义的行为确实是您不希望在您的程序中发生的事情(除了错误行为之外,它也是一个 安全性 问题)。肯定有加速分配的方法,例如通过使用池,处理碎片等。或者还有其他类型的哈希映射更适合特定用例。这个主题被很好地研究了。我建议您探索这些,并强烈建议您不要故意向您的程序添加未定义的行为。

Is it OK to to add negligible risks of errors for performance gains? (fixed hash map bucket size)

当某些程序循环 10 亿次时,可忽略的风险(意味着低概率)变得明显......不幸的是,经过多年的生产使用,这已成为许多错误的根源。这对通信协议设计产生了很大的影响,如今强大的验证工具被用来测试任何微小但可能的违规行为。

只有在人类生命没有受到损害、影响很小并且修复错误的成本远远高于错误可能产生的后果或损害的情况下,才能承认这一点。但有时仅仅确定影响可能代价高昂,因此建议不修复错误的情况很少。