バグを説明する
問題#2238で@animalizeによって報告された
ZSTD_e_endendディレクティブと出力バッファサイズ> = ZSTD_compressBound()を使用する場合、ジョブ番号はZSTDMT_computeNbJobs()関数によって計算されます。 この関数は、 nbWorkers
応じて異なる数のジョブを生成します。
予想される行動
zstdマルチスレッド圧縮の出力は、スレッドの数に依存しない必要があります。
修理
ZSTDMT_computeNbJobs()
をnbWorkers
独立させます。回避策
このバグを回避する必要がある場合は、ZSTD_e_endでストリーミングジョブを開始しないでください。 ZSTD_e_endを呼び出す前に、少なくとも1バイトの入力をZSTD_e_continueで渡すか、出力バッファーが< ZSTD_compressBound(inputSize)
ことを確認してください。
マルチスレッドzstd
の結果は、スレッドの
実際、サポートされている機能は、_streaming_マルチスレッドzstd
の結果がスレッドのnbに依存しないことです。
(そしてそれがzstd
CLIによって使用されるものです)。
この定義により、別の潜在的な修正を検討することができます。
以下のための1つのパスのショートカット使用しないZSTD_e_end
nbWorkers >= 1
、
この問題を引き起こすのはワンパスモードへの委任だからです。
これは、シングルパスMTコンプレッサーを適応させるよりも混乱が少ない可能性があります。
これは、この保証を提供するように設計されたことはありません。
もう1つの(潜在的にプラスの)副作用は、ストリーミングマルチスレッド圧縮が(ブロッキング)シングルパスモードに委任されなくなるため、_常に_非ブロッキングであることが保証されることです。
_edit _: ZSTD_e_flush
およびZSTD_e_end
ディレクティブを受信すると、MT APIコントラクトが最小の前進から最大の進歩。
もう1つの(潜在的にプラスの)副作用は、ストリーミングマルチスレッド圧縮がブロッキングモードに委任されなくなるため、常にノンブロッキングであることが保証されることです。
私はかつて、マルチスレッド圧縮で常にブロックしているZSTD_compressStream3()
関数を追加することを提案したかったのです。
発信者が非ブロッキングの進行状況をチェックし続ける場合、それは非常に不便です。
編集:見つかったばかりですが、進行状況の確認はそれほど不便ではありません:
do {
zstd_ret = ZSTD_compressStream2(self->cctx, &out, &in, ZSTD_e_continue);
} while (out.pos != out.size && in.pos != in.size && !ZSTD_isError(zstd_ret));
ただし、常にZSTD_compressStream3()
ブロックすることをお勧めします。少し速くなる可能性があり、IMOの多くのプログラマーユーザーは圧縮の進行状況を取得する必要がありません。
これは、シングルパスMTコンプレッサーを適応させるよりも混乱が少ない可能性があります。
これは、この保証を提供するように設計されたことはありません。
ええ、それはおそらく簡単です。 シングルパスMTコンプレッサーのすべてのジョブを一度に起動する必要があることを忘れていました。
私はかつて、マルチスレッド圧縮で常にブロックしているZSTD_compressStream3()関数を追加することを提案したかったのです。
一般に、人々がストリーミング圧縮ループを作成する方法では、最大限の前進をしないことはひどく不便であってはなりません。 このようなものを追加する場合、新しいAPIは必要ありません。 おそらく、それを制御するために圧縮パラメーターを追加する必要があるでしょう。 しかし、私は現在それの大きな必要性を見ていません。
最も参考になるコメント
ええ、それはおそらく簡単です。 シングルパスMTコンプレッサーのすべてのジョブを一度に起動する必要があることを忘れていました。
一般に、人々がストリーミング圧縮ループを作成する方法では、最大限の前進をしないことはひどく不便であってはなりません。 このようなものを追加する場合、新しいAPIは必要ありません。 おそらく、それを制御するために圧縮パラメーターを追加する必要があるでしょう。 しかし、私は現在それの大きな必要性を見ていません。