Parallel processing 密钥的替代哈希表相等性测试

Parallel processing 密钥的替代哈希表相等性测试,parallel-processing,mapping,common-lisp,hashtable,Parallel Processing,Mapping,Common Lisp,Hashtable,SBCL评测显示我的一个常见Lisp哈希表函数占用了大量时间。该函数比较两个哈希表以确定它们是否具有相同的键: (defun same-keys (ht1 ht2) "Returns t if two hash tables have the same keys." (declare (hash-table ht1 ht2)) (when (= (hash-table-count ht1) (hash-table-count ht2)) (maphash (lambda (h

SBCL评测显示我的一个常见Lisp哈希表函数占用了大量时间。该函数比较两个哈希表以确定它们是否具有相同的键:

(defun same-keys (ht1 ht2)
  "Returns t if two hash tables have the same keys."
  (declare (hash-table ht1 ht2))
  (when (= (hash-table-count ht1) (hash-table-count ht2))
    (maphash (lambda (ht1-key ht1-value)
               (declare (ignore ht1-value))
               (unless (gethash ht1-key ht2)
                 (return-from same-keys nil)))
             ht1)
    t))
如果哈希表总是使用
fixnum
#eql
,有没有办法加快速度?我还加载了
lparallel
库,但是在这种情况下,以某种方式并行化函数有意义吗


编辑:哈希表的大小可以是10到100个条目。ht键的范围从100扩展到9999999999,但在该范围内实际使用的可能的修饰符总数很少。每个ht值都是t或列表。所有哈希表的键值关联在加载时设置。通过复制现有哈希表并增量添加或删除条目,可以在运行时创建新的哈希表。例行的哈希表读取、写入和复制似乎不是问题。

除了低级优化之外,它还取决于哈希表的大小和键的可能值范围

如果密钥范围不比大小小很多,那么使用向量而不是哈希表可能会更快。如果大小很小(小于20-50),但范围很大(例如UUID),那么Alist可能更适合

如果写入这些哈希表不是瓶颈,那么您可以将哈希表包装为包含一些辅助数据结构的对象,以便进行键比较。这可能是标记所用密钥的位向量,或者是所有所用密钥的完整自定义哈希,或者(如果大小和范围真的很大)类似bloom过滤器的东西

如果您的问题在某个维度上足够大,从而使其值得开销,那么并行化可能是有意义的:例如,独立比较的频率非常高,或者每个哈希表的键数非常大

一种可能的低级优化是使用
循环
而不是
映射哈希
,大多数情况下可以将其编译为更快的代码:

(loop :for key1 :being :the :hash-keys :of ht1
      :always (nth-value 1 (gethash key1 ht2)))

感谢您对折衷方案进行的最出色的讨论。如果这有助于进一步了解的话,上面的编辑与权衡有关。谢谢。考虑到
lparallel:pmap
cognate函数,我想知道类似的东西是否适用于哈希表上的映射。同样令人惊讶的是,在我的应用程序中,loop似乎比maphhash稍微慢一些。接下来,我还看到了alexandria库中的一个函数,它只映射哈希表中的键:
(alexandria:maphhash keys fn ht)
。但这并不比前面提到的另外两个选择更快,至少在我的申请中是这样。