私は、NumPy配列をデータベースに書き込むためにPythonでzlib
パッケージを使用して加速しようとしている行列代数の問題の中間生成物をキャッシュするシステムを開発中です後で取り出す。私はGILをリリースすることでスピードの向上とマルチスレッド化のためにCythonを利用したいと思っています。zlibを使ってCythonのNumPy配列を圧縮する
コード私はほとんど機能していますが、私はかなり困惑していることがいくつかの問題のためにあります。まず、compress2
関数をステータスコード0で返すCライブラリからインポートしたにもかかわらず(つまり、圧縮に成功した)、出力バッファのセットアップに関係なく、出力は常に切り捨てられます。次に、私がしたいことをしてNumPy配列を圧縮しようとすると、圧縮関数は最初のバイトだけを返します。
#include <zlib.h>
cimport numpy as np
from libc.stdio cimport printf
from libc.stdlib cimport malloc, free
cdef extern from "zlib.h":
ctypedef unsigned char Bytef
ctypedef unsigned long uLongf
ctypedef long unsigned uLong
int compress2 (Bytef *, uLongf *, Bytef *, uLong, int)
def __cache_write(np.ndarray weights):
weight_string = weights.tostring()
cdef char* c_weight_string = weight_string
cdef char compressed[1000]
cdef uLongf destlen = sizeof(compressed)
cdef int status = compress2(<Bytef *>compressed, &destlen, <Bytef *>c_weight_string, sizeof(c_weight_string), 6)
cdef bytes result = compressed
return status, result
私が切り捨てられた出力を得ている理由の一部は、バイトの文字列ではなく、ASCIIまたは任意の文字列を返す.tostring()
機能に関係していることをいくつかの漠然とした考えを持っています。しかし、関数にPython文字列を受け入れると、切り捨てられた出力も得られます(例えば、'abc'
)。
In [5]: __cache_write(np.ones(10))
Out[5]: (0, 'x\x9cKLJf')
...
In [7]: zlib.compress(np.ones(10).tostring())
Out[7]: 'x\x9cc`\x00\x81\x0f\xf6\x0cT\xa2\x01\xbf\xad\x0b\xd7'
これは私の専門分野ではないので、新生児の間違いをお詫び申し上げます。
アップデート1:
最初の回答が指摘したように、私はcompress2
関数の呼び出しを台無しに。 sizeof(c_weight_string)
をlen(weight_string)
に置き換えると、すべての問題を解決していないものの、見た目が良くなります。
私は文字列であると'abc'
ようなもので、それをしようとする入力引数を切り替えると、私は"x\x9cKLJ\x06\x00\x02M\x01'"
は、Python zlib
パッケージが、私の関数から'x\x9cKLJf\xc0\t\xe4\xfb7\xb6\xd430<\x10\x87\xd06h\xd2\x8cP\xfa\x83\x1cD^\x01\xa4\x0e'
を呼び出して取得します。 (これは正確に何が圧縮されているかと関係があるかもしれませんが、解凍しようとすると終端文字のエラーが表示され、何か他のことが起こっていることを示唆しています)。NumPyベクトルを圧縮しようとすると、ちょうど最初の数バイトで羽目になる:
'x\x9cc`'
の代わりに:
OK、ありがとう。 compress関数の第4引数は、間違いなく問題の少なくとも一部でした。私はまだ私の機能にいくつかの問題があると思っています。 (これはもっと分かりやすいように、もっと多くの音符で質問を更新します。) もうひとつ注意しておきますが、これは関数の一部であり、GILのロックを解除できるようにしたいと思います。私はC圧縮部分が以前よりも簡単になると予想していたと思う。 – josephkibe
私は100%確信していませんが、Pythonのzlibモジュールと 'numpy.savez_compressed'がGIL自体をリリースしていると思われます。残りの問題についてはわかりません。 – DavidW