用Scipy.sparse实现GF(256)中的快速稀疏矩阵点乘法



我需要提高算法的速度。该方法以两个矩阵为自变量,进行点乘法运算。唯一的问题是元素必须在GF(256(中作为八位字节相乘,然后作为XOR相加。由于我处理的是非常大的稀疏矩阵,所以性能非常糟糕。

def matrix_oct_mult(U, V, OCT_EXP, OCT_LOG):
temp_sum = 0
if shape(U)[1] == None and shape(V)[1] == None:
for i in range(len(U)):
temp_sum = oct_sum(temp_sum, oct_mult(U[i], V[i], OCT_EXP, OCT_LOG))
return temp_sum
assert shape(U)[1] == shape(V)[0], "Wrong size requirements for matrix dot multiplication"
temp_sum = 0
W = sp.lil_matrix((shape(U)[0], shape(V)[1]))
for i in range (shape(U)[0]):
for z in range(shape(V)[1]):
for j in range (shape(U)[1]):
temp_sum = oct_sum(temp_sum, oct_mult(U[i, j], V[j, z], OCT_EXP, OCT_LOG))
W[i, z] = temp_sum
temp_sum = 0
return W

正如你可能看到的,我试过lil类,但表现仍然很糟糕。

有什么有效的解决方法吗?

由于解释了Python,嵌套的for循环的性能非常差。而C中的等效CCD_ 2循环将是快速的。所以编译后的代码会带来最佳性能。

出于这个原因,我编写了一个名为galois的Python库,它扩展了NumPy数组以在galois字段中操作。我用Python编写代码,但JIT使用Numba进行编译,因此Galois字段算法与本地NumPy数组算法一样快,或者几乎一样快,请参阅此性能比较。

该库支持使用标准二进制运算符(+@等(和标准NumPy线性代数函数的Galois域矩阵上的线性代数。这些例程中的大多数也是为了提高速度而JIT编译的。

我相信你正在尝试对两个矩阵((M,N) x (N,K)(进行矩阵乘法运算。以下是在galois中执行此操作的示例。

In [1]: import galois                                                                                                                                                                          
# Create the GF(2^8) field using AES's irreducible polynomial -- your's may be different
In [2]: GF = galois.GF(2**8, irreducible_poly=0x11b)                                                                                                                                           
In [3]: print(GF.properties)                                                                                                                                                                   
GF(2^8):
characteristic: 2
degree: 8
order: 256
irreducible_poly: x^8 + x^4 + x^3 + x + 1
is_primitive_poly: False
primitive_element: x + 1
In [4]: A = GF.Random((3,4)); A                                                                                                                                                                
Out[4]: 
GF([[ 35, 130, 167, 111],
[ 58, 161, 194, 200],
[244,  65, 160,   8]], order=2^8)
In [5]: B = GF.Random((4,5)); B                                                                                                                                                                
Out[5]: 
GF([[ 50,  59,  23,  34,  38],
[ 16,  59, 162,  80, 250],
[205, 145, 114,   9,  40],
[212, 250, 162, 210,  72]], order=2^8)
In [6]: A @ B                                                                                                                                                                                  
Out[6]: 
GF([[144, 236, 142,  90,  89],
[ 83, 171,  34,   2, 117],
[192,   1,  20, 208, 127]], order=2^8)

最新更新