md5 numpy数组的快速方法

时间:2018-08-13 22:49:05

标签: python numpy hash md5

我正在用python 2.7中的numpy的一维数组和成千上万的uint64数字进行操作。分别计算每个数字的md5的最快方法是什么?

在调用md5函数之前,每个数字都必须转换为字符串。我在许多地方读到,遍历numpy的数组并用纯python做事情实在太慢了。有什么办法可以避免?

4 个答案:

答案 0 :(得分:3)

您可以为接受NumPy数组的OpenSSL的MD5()函数编写包装。我们的基准将是纯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 _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']

对于大型阵列,速度要快15倍(老实说,我对此感到有些失望...)

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)

答案 1 :(得分:1)

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

>>> import struct, hashlib
>>> a = struct.pack( '<Q', 0x423423423423 )
>>> a
'#4B#4B\x00\x00'
>>> hashlib.md5( a ).hexdigest()
'de0fc624a1b287881eee581ed83500d1'
>>> 

因为没有转换,只是简单的字节副本,所以这肯定会加快处理速度。

另外,gettig hexdigest()可能会被digest()取代,它返回二进制数据,这比将其转换为十六进制字符串要快。根据您以后计划使用这些数据的方式,这可能是一个好方法。

答案 2 :(得分:0)

dialog.setMessage(message);

答案 3 :(得分:-1)

您可以应用一个函数,该函数会将函数映射到数组上。这是最简单的操作。 link

在示例中,我仅将1添加到原始数组。您可以根据需要将其转换为MD5。

import numpy as np
x = np.array([1, 2, 3, 4, 5])
f = lambda x: x + 1
result = f(x)