Python 实现md5的快速方法一个numpy阵列

Python 实现md5的快速方法一个numpy阵列,python,numpy,hash,md5,Python,Numpy,Hash,Md5,我正在使用Python2.7中包含数千个uint64数字的numpy 1d数组。计算每个数字的md5的最快方法是什么 在调用md5函数之前,必须将每个数字转换为字符串。我在很多地方都读到,迭代numpy的数组并用纯python做一些事情非常慢。有什么办法可以避免这种情况吗?我绝对建议避免将uint64转换为字符串。您可以使用struct获取二进制数据,这些数据随后可以馈送到hashlib.md5(): 导入结构,hashlib >>>a=struct.pack(“您可以为OpenSSL的MD5(

我正在使用Python2.7中包含数千个uint64数字的numpy 1d数组。计算每个数字的md5的最快方法是什么


在调用md5函数之前,必须将每个数字转换为字符串。我在很多地方都读到,迭代numpy的数组并用纯python做一些事情非常慢。有什么办法可以避免这种情况吗?

我绝对建议避免将
uint64
转换为字符串。您可以使用
struct
获取二进制数据,这些数据随后可以馈送到
hashlib.md5()

导入结构,hashlib
>>>a=struct.pack(“您可以为OpenSSL的
MD5()
函数编写一个接受NumPy数组的包装器。我们的基线将是一个纯Python实现

使用cffi创建包装器:

import cffi

ffi = cffi.FFI()

header = r"""
void md5_array(uint64_t* buffer, int len, unsigned char* out);
"""

source = r"""
#include <stdint.h>
#include <openssl/md5.h>

void md5_array(uint64_t * buffer, int len, unsigned char * out) {
    int i = 0;
    for(i=0; i<len; i++) {
        MD5((const unsigned char *) &buffer[i], 8, out + i*16);
    }
}
"""

ffi.set_source("_md5", source, libraries=['ssl'])
ffi.cdef(header)

if __name__ == "__main__":
    ffi.compile()
并将两者进行比较:

import numpy as np
import hashlib

data = np.arange(16, dtype=np.uint64)
out = [hashlib.md5(i).digest() for i in data]

print(data)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15]
print(out)
# [b'}\xea6+?\xac\x8e\x00\x95jIR\xa3\xd4\xf4t', ... , b'w)\r\xf2^\x84\x11w\xbb\xa1\x94\xc1\x8c8XS']

out = md5_array(data)

print(out)
# [b'}\xea6+?\xac\x8e\x00\x95jIR\xa3\xd4\xf4t', ... , b'w)\r\xf2^\x84\x11w\xbb\xa1\x94\xc1\x8c8XS']
对于大型阵列,速度大约快15倍(老实说,我对此有点失望…)


这种转换的意义是什么?如何使用md5字符串,而原始float64不能使用?我只想将uint64转换为字符串,然后尽快获得它们的md5。稍后将使用这些md5字符串。我非常确定@lenik是正确的,并且您不需要这种转换。在应用md5之前进行转换似乎是非常简单的试图优化一个甚至还不起作用的代码。您是否可以尝试应用lenik的建议?这是整个数组的MD5,否?OP想单独计算每个元素的MD5。@NilsWerner否,这是一个元素单独的MD5。如果您需要解释如何在元素上循环,我可以为您这样做你也是。啊,我明白了。AttributeError:模块“\u md5”没有属性“lib”,为什么?我不确定。可能你的cffi版本很旧,或者你的目录中有一个
\u md5.py
文件。
import numpy as np
import _md5

def md5_array(data):
    out = np.zeros(data.shape, dtype='|S16')

    _md5.lib.md5_array(
        _md5.ffi.from_buffer(data),
        data.size,
        _md5.ffi.cast("unsigned char *", _md5.ffi.from_buffer(out))
    )
    return out
import numpy as np
import hashlib

data = np.arange(16, dtype=np.uint64)
out = [hashlib.md5(i).digest() for i in data]

print(data)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15]
print(out)
# [b'}\xea6+?\xac\x8e\x00\x95jIR\xa3\xd4\xf4t', ... , b'w)\r\xf2^\x84\x11w\xbb\xa1\x94\xc1\x8c8XS']

out = md5_array(data)

print(out)
# [b'}\xea6+?\xac\x8e\x00\x95jIR\xa3\xd4\xf4t', ... , b'w)\r\xf2^\x84\x11w\xbb\xa1\x94\xc1\x8c8XS']
data = np.arange(100000, dtype=np.uint64)

%timeit [hashlib.md5(i).digest() for i in data]
169 ms ± 3.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit md5_array(data)
12.1 ms ± 144 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
>>> import hashlib
>>> import numpy as np
>>> arr = np.array([1, 2, 3, 4, 5], dtype="uint64")
>>> m = hashlib.md5(arr.astype("uint8"))
>>> m.hexdigest()
'7cfdd07889b3295d6a550914ab35e068'