【问题标题】:Implementing Zobrist hashing in Javascript在 Javascript 中实现 Zobrist 散列
【发布时间】:2014-09-08 21:53:12
【问题描述】:

我需要在 Javascript 中为国际象棋引擎实现 Zobrist 散列,我想知道实现这一点的最佳方法是什么。现在,我不是计算机科学家,也从来没有正式的算法和数据结构类,所以如果我在这方面有点偏离,我很抱歉......

据我了解,我需要一个 64 位散列函数来将位置编码为低于该位置的位置会引发太多冲突。现在在 javascript 中,我只能访问 32 位数字。还有一个问题是我如何实现哈希表以及它是如何由节点中的 V8 引擎“在幕后”实现的。

我可以将它作为长度为 TABLESIZE 的 javascript 数组,然后执行以下操作:

var table = new Array();

table[hashCodeLo % TABLESIZE] = {
    hashCodeLo: hashCodeLo,
    hashCodeHi: hashCodeHi,
    someProperty: someValue
};

其中 hashCodeLo 和 hashCodeHi 表示代码的高 32 位和低 32 位,TABLESIZE

var table = {};

table[hashCode] = {
    someProperty: someValue
}

这里的 hashCode 只是我的 64 位 hashCode 的字符串表示。由于我不确定“字典模式”如何在幕后工作,我不确定哪个更好。另外我不知道我是否通过使用“1983981918391”之类的键而不是更紧凑的表示形式来使用更多内存:

hashCode = String.fromCharCode(FIRST_16BITS, SECOND_16BITS, THIRD_16BITS, FOURTH_16BITS)

我什至不确定这是否符合我的预期......

由于这是引擎的关键部分,因此我希望尽可能多地发挥性能,因此不胜感激。

【问题讨论】:

  • 你在哪个环境下运行 v8 怎么样?

标签: javascript performance hashtable v8


【解决方案1】:

据我了解,我需要一个 64 位散列函数来将位置编码为低于该位置会引发太多冲突。

至少不适用于transposition table - 它几乎不会有 264 的大小。

如果您要实现此功能来对位置本身进行编码(并通过比较 64 位哈希来检测一些冲突),那么是的,如果这是文献推荐的,您可以使用 64 位(尽管您可能想尝试52 位也是如此)。

现在在 javascript 中我只能访问 32 位数字。

没有。 JavaScript 中的数字是 64 位浮点数,您最多可以在其中精确存储 52 位整数。只有位运算符仅限于 32 位整数(如有必要,数字将被强制转换为整数)。

但是,数组本身的长度限制为 232;但即使这样也应该绰绰有余。

还有一个问题是我如何实现哈希表以及它是如何由节点中的 V8 引擎“在幕后”实现的。

只需将其实现为数组。尝试用 null 值填充它以进行初始化,并查看非稀疏数组是否表现更好。如果您关心性能,请测试一下

hashCodeLo 和 hashCodeHi 分别表示代码的高低 32 位,TABLESIZE

我会使用 Uint32Array 而不是对象数组。根据somePropertysomeValue 是什么,您可能只想将对象的索引存储在普通数组或标量本身(可能使用DataView)中。代码可能如下所示:

var zobrist = new Uint32Array(13 * 2 * 64 * 2) // pieces * colors * fields * 64/32
for (var i=0; i<zobrist.length; i++)
    zobrist[i] = Math.random() * 4294967296;

var table = new Uint32Array(3 * tablesize);

function hash(hi, lo, piece, color, field) {
    hi ^= zobrist[piece * 128 + color * 64 + field];
    lo ^= zobrist[piece * 128 + color * 64 + field + 1];

    var i = lo % tablesize;
    if (table[i] == hi && table[i+1] == lo) {
        // collision
    } else {
        table[i] = hi; table[i+1] = lo;
        // do what you want with table[i+2]
    }
}

【讨论】:

  • >没有。你是怎么得出这个结论的?有超过 264 个可能的国际象棋位置,您几乎不会尝试存储(甚至枚举)它们。
  • 这似乎是我读过的国际象棋文献中的共识。我知道有超过 2^64 个可能的国际象棋位置,但我再次需要 64 位的密钥来检测合理数量的碰撞。将完整位置存储在转置表中似乎很浪费,而且我还没有看到任何引擎可以做到这一点。通过将其减少到 64 位,我假设您在哈希表大小和未检测到的冲突数之间取得了不错的折衷。我没有对此进行数学计算,我只是按照其他人所做的...
  • 啊,我现在看到您将使用散列来编码实际位置,而不仅仅是转置表索引。我认为 2^64 的哈希表大小会有点大……
猜你喜欢
  • 1970-01-01
  • 2021-02-17
  • 2014-01-16
  • 2022-08-23
  • 2013-03-18
  • 1970-01-01
  • 2020-11-08
  • 2021-01-28
  • 2013-02-18
相关资源
最近更新 更多