【问题标题】:Fast sparse matrix dot multiplication in GF(256) with Scipy.SparseGF(256) 中的快速稀疏矩阵点乘法与 Scipy.Sparse
【发布时间】:2021-02-21 15:13:51
【问题描述】:

我需要提高算法的速度。该方法将两个矩阵作为参数并执行点乘。唯一的问题是元素必须在 GF(256) 中作为八位字节相乘,然后作为异或相加。 由于我正在处理非常大的稀疏矩阵,因此性能很糟糕。

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 不是一种编译语言,矩阵运算的嵌套循环总是异常缓慢。您应该重组您的问题以使用标准矩阵运算,或者您应该用您选择的编译语言编写它。
  • 我看不出您在哪里利用UV 或结果W 的稀疏性。对于像这样的迭代,普通的ndarray(甚至列表列表)会更好。即使使用lil 对稀疏矩阵的元素访问也很慢。

标签: python performance scipy sparse-matrix galois-field


【解决方案1】:

由于 Python 是被解释的,嵌套的 for 循环众所周知的性能很差。而 C 中等效的 for 循环会很快。所以最好的性能将来自编译的代码。

出于这个原因,我编写了一个名为 galois 的 Python 库,它扩展了 NumPy 数组以在 Galois 域中进行操作。我用 Python 编写了代码,但 JIT 使用 Numba 对其进行了编译,因此 Galois 域算术与原生 NumPy 数组算术一样快或几乎一样快,请参阅performance comparison

该库支持使用标准二元运算符(+@ 等)和普通 NumPy 线性代数函数对伽罗瓦域矩阵进行线性代数。这些例程中的大多数也是 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)

【讨论】:

    猜你喜欢
    • 2015-04-07
    • 1970-01-01
    • 2015-04-08
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    相关资源
    最近更新 更多