3 回答

TA貢獻1752條經驗 獲得超4個贊
您可以為MD5()接受NumPy數(shù)組的OpenSSL函數(shù)編寫包裝器。我們的基準將是純Python實現(xiàn)。
使用cffi創(chuàng)建包裝器:
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)

TA貢獻1828條經驗 獲得超3個贊
我絕對建議避免轉換uint64為字符串。您可以struct用來獲取二進制數(shù)據(jù),然后可以將其提供給hashlib.md5():
>>> import struct, hashlib
>>> a = struct.pack( '<Q', 0x423423423423 )
>>> a
'#4B#4B\x00\x00'
>>> hashlib.md5( a ).hexdigest()
'de0fc624a1b287881eee581ed83500d1'
>>>
因為沒有轉換,只有簡單的字節(jié)副本,所以這肯定會加快處理速度。
另外,hexdigest()可以將gettig替換為digest(),以返回二進制數(shù)據(jù),這比將其轉換為十六進制字符串的速度更快。根據(jù)您以后計劃使用該數(shù)據(jù)的方式,這可能是一個好方法。

TA貢獻1744條經驗 獲得超4個贊
>>> 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'
添加回答
舉報