11

4 億 4000 万の非ヌル ポイントを持つ次元 (170k x 170k) の Scipy CSC スパース マトリックス "sm" と、いくつかの非ヌル ポイントを持つスパース CSC ベクトル "v" (170k x 1) が与えられた場合、可能なものはありますか?操作のパフォーマンスを向上させるために行われます。

resul = sm.dot(v)

?

現在、約1秒かかります。CSR としてマトリックスを初期化すると、時間が最大 3 秒増加したため、CSC のパフォーマンスが向上しました。

SM は製品間の類似度のマトリックスで、V はユーザーが購入またはクリックした製品を表すベクトルです。したがって、すべてのユーザーの sm は同じです。

Ubuntu 13.04、Intel i3 @3.4GHz、4 コアを使用しています。

SO について調べていると、Ablas パッケージについて読みました。ターミナルに次のように入力しました。

~$ ldd /usr/lib/python2.7/dist-packages/numpy/core/_dotblas.so

その結果:

    linux-vdso.so.1 =>  (0x00007fff56a88000)
    libblas.so.3 => /usr/lib/libblas.so.3 (0x00007f888137f000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8880fb7000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8880cb1000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f888183c000)

私が理解したところでは、これは私が既に Ablas の高性能パッケージを使用していることを意味します。このパッケージがすでに並列コンピューティングを実装しているかどうかはまだわかりませんが、実装されていないようです。

マルチコア処理はパフォーマンスの向上に役立ちますか? もしそうなら、Pythonで役立つライブラリはありますか?

これをCythonに実装するというアイデアも検討していましたが、これが良い結果につながるかどうかはわかりません。

前もって感謝します。

4

2 に答える 2

13

疎行列乗算ルーチンは C++ で直接コーディングされており、ソースをざっと見てみる限り、最適化されたライブラリへのフックはないようです。さらに、計算を最小限に抑えるために、2 番目の行列がベクトルであるという事実を利用していないようです。そのため、疎行列の根幹にアクセスし、乗算アルゴリズムをカスタマイズすることで、おそらくかなり高速化できます。次のコードは、純粋な Python/Numpy でこれを行います。ベクトルに実際に「いくつかの非 null ポイント」がある場合、scipy の C++ コードの速度と一致します。Cython で実装した場合、速度の向上は顕著になるはずです。

def sparse_col_vec_dot(csc_mat, csc_vec):
    # row numbers of vector non-zero entries
    v_rows = csc_vec.indices
    v_data = csc_vec.data
    # matrix description arrays
    m_dat = csc_mat.data
    m_ind = csc_mat.indices
    m_ptr = csc_mat.indptr
    # output arrays
    sizes = m_ptr.take(v_rows+1) - m_ptr.take(v_rows)
    sizes = np.concatenate(([0], np.cumsum(sizes)))
    data = np.empty((sizes[-1],), dtype=csc_mat.dtype)
    indices = np.empty((sizes[-1],), dtype=np.intp)
    indptr = np.zeros((2,), dtype=np.intp)

    for j in range(len(sizes)-1):
        slice_ = slice(*m_ptr[[v_rows[j] ,v_rows[j]+1]])
        np.multiply(m_dat[slice_], v_data[j], out=data[sizes[j]:sizes[j+1]])
        indices[sizes[j]:sizes[j+1]] = m_ind[slice_]
    indptr[-1] = len(data)
    ret = sps.csc_matrix((data, indices, indptr),
                         shape=csc_vec.shape)
    ret.sum_duplicates()

    return ret

何が起こっているかの簡単な説明: CSC 行列は 3 つの線形配列で定義されます。

  • dataゼロ以外のエントリが含まれ、列の主要な順序で格納されます。
  • indicesゼロ以外のエントリの行が含まれます。
  • indptr行列の列数よりも 1 つ多いエントリがあり、 column 内の項目jは で見つかりdata[indptr[j]:indptr[j+1]]、 rows 内にありますindices[indptr[j]:indptr[j+1]]

したがって、スパース列ベクトルを掛けるには、列ベクトルを繰り返し処理しdataindices各ペアに対して、行列の対応する列を抽出し、 、つまりおよび(d, r)を掛けます。ddata[indptr[r]:indptr[r+1]] * dindices[indptr[r]:indptr[r+1]]

于 2013-09-03T19:13:52.117 に答える