我正在创建一个在pyarrow.plasma
中存储大型numpy数组的系统。
我想给每个数组一个唯一的、确定性的 plasma.ObjectID
,np.array
是不可散列的
我目前的方法是:
import numpy as np
from pyarrow import plasma
def int_to_bytes(x: int) -> bytes:
return x.to_bytes(
(x.bit_length() + 7) // 8, "big"
) # https://stackoverflow.com/questions/21017698/converting-int-to-bytes-in-python-3
def get_object_id(arr):
arr_id = int(arr.sum() / (arr.shape[0]))
oid: bytes = int_to_bytes(arr_id).zfill(20) # fill from left with zeroes, must be of length 20
return plasma.ObjectID(oid)
但这很容易失败,例如:
arr = np.arange(12)
a1 = arr.reshape(3, 4)
a2 = arr.reshape(3,2,2)
assert get_object_id(a1) != get_object_id(a2), 'Hash collision'
# another good test case
assert get_object_id(np.ones(12)) != get_object_id(np.ones(12).reshape(4,3))
assert get_object_id(np.ones(12)) != get_object_id(np.zeros(12))
它还涉及对数组求和,这对于大型数组可能非常慢。
请随意假设arr
的dtype
将是np.uint
或np.int
我知道我认为不可能永远不会有散列冲突(我只有20个字节的ID,并且有超过2^20个)可能的输入,所以我只是在寻找 a) 计算起来更便宜 b) 不太可能在实践中失败
或者,理想情况下,两者都有
hashlib模块有一些从字节字符串(通常用于CRC)计算哈希的例程。可以使用
ndarray.tobytes
将数据数组转换为字节字符串,但是示例仍然会失败,因为这些数组具有相同的字节,但形状不同。所以你也可以把形状散列出来Exmaple:
我不是blake2b方面的专家,所以你必须自己做研究,找出碰撞的可能性
我不知道为什么要标记
pyarrow
,但是如果您想在pyarrow数组上执行相同的操作而不转换为numpy,那么您可以使用arr.buffers()
获取数组的缓冲区,并将这些缓冲区(将有多个,有些可能是None
)转换为使用buf.to_pybytes()
的字节字符串。只是散列所有缓冲区。这里不必担心形状,因为pyarrow数组总是一维的相关问题 更多 >
编程相关推荐