gzipやzlibなどの一般的なファイル圧縮プログラムは、入力ファイルを取り込んで圧縮し、可能な場合、より小さい出力ファイルを作り出す。出力ファイルは定義済みのフォーマットを持っており、これにより、ファイル解凍プログラム(gzipやzlibなど)は、圧縮された出力ファイルを入力として取り込んで解凍し、元の入力ファイルと同一の解凍されたファイルを作り出すことができる。圧縮されたファイルは、入力ファイルのデータの連続するブロックに対応する一連のブロックを含んでいる。圧縮されたファイルの各ブロックは、DEFLATE圧縮データ・フォーマット仕様バージョン1.3、RFC 1951で定義されている可逆圧縮データ・フォーマットに従う。DEFLATE仕様によれば、入力ファイルの各ブロックは、LZ方式アルゴリズム(例えば、LZ77)とハフマン・コーディングの組み合わせを使用して圧縮される。例えば、「A Universal Algorithm for Sequential Data Compression」Ziv J.、Lempel A.、情報理論に関するIEEEトランザクション、第23巻3号、337〜343ページ、「A Method for the Construction of Minimum Redundancy Codes」Huffman、D. A.、無線技術学会の会報、1952年 9月、第40巻9号、1098〜1101ページを参照されたい。
LZ77圧縮アルゴリズム(及びその多くの変形)は、入力データ・ストリーム内の繰り返し出現するデータ又は文字列を、入力データ・ストリーム内の以前に出現した文字列へのバック・ポインタで置換することによって、可逆方式で入力データ・ストリームを圧縮する。文字列は、1つ又は複数の連続する文字である。各バック・ポインタは、順序付けられた対(長さ、距離)である。長さは、入力データ・ストリーム内の現在のスキャン位置での文字列の文字数を示し、この文字列は、現在のスキャン位置から後方の距離によって指定された、入力ストリーム内の以前の位置から始まる同じ文字列と一致する。バック・ポインタは、次の記述、すなわち「次の長さの各文字は、圧縮されていないストリーム内のそれらの文字の後方の、距離の文字数だけ正確に離れた各文字に等しい」と同等なものとして説明されている。アルゴリズムは、繰り返される文字列の文字をバック・ポインタで置換することによって圧縮を実現する。さらに具体的には、LZ77アルゴリズムは、入力データ・ストリーム内を、現在のスキャン位置から後方に検索し、1つのバック・ポインタで置換するための文字列の一致(例えば、もしあれば、最長の一致する文字列)を検出する。適切な一致が検出された場合、アルゴリズムは一致する文字列へのバック・ポインタを生成し、検出されない場合、アルゴリズムはリテラル入力文字、例えば、現在のスキャン位置の3文字を効率的に生成し、現在のスキャン位置を更新する。DEFLATE仕様は、アルゴリズムが入力文字を置換するためのバック・ポインタを生成するのではなく入力文字を生成する場合を指して、「リテラル」という用語を使用する。したがって、LZ77圧縮の実際の出力は、リテラルとバック・ポインタのストリーム(及び、必要に応じて、下でより詳細に説明されるように、各リテラル及びバック・ポインタの頻度のヒストグラム)である。現在の仕様では、リテラルとバック・ポインタは「トークン」と呼ばれる。したがって、LZ77圧縮の出力はトークンのストリームである。達成される圧縮量は、主に、入力データ・ストリーム内で文字列が繰り返される度合いと繰り返される文字列の長さとに依存している。
DEFLATE仕様は、一般にプレフィックス・コーディングとも呼ばれるハフマン・コーディングについて、次のように説明している。すなわち「プレフィックス・コーディングは、ビット列(コード)によって既知のアルファベットからシンボルを表現し、シンボルごとに1つのコードである。この方法では、さまざまな長さのビット列によって、さまざまなシンボルが表現されることが可能であるが、パーサは、エンコードされた文字列をシンボルごとに常に一義的に構文解析することができる。アルファベットのシンボルの頻度がわかっていると仮定した場合、ハフマン・アルゴリズムは最適なプレフィックス・コード(そのアルファベットに対して使用できる最小のビット数のプレフィックス・コードを使用して、上記のシンボルの頻度で文字列を表現する)を構築することができる。このようなコードをハフマン・コードと呼ぶ」。DEFLATE仕様によれば、2つの区別可能なアルファベットが識別される。一方のアルファベットでは、シンボルは、リテラルの値(エントリ0〜256)、及びバック・ポインタの長さに関連付けられた値又はインデックス(エントリ257〜285)である。他方のアルファベットでは、シンボルは、バック・ポインタの距離に関連付けられた値又はインデックスである(エントリ0〜29)。下でより詳細に説明されているように、2つのアルファベットの各々についてハフマン・コード・テーブルが作成される。
DEFLATE仕様によれば、出力ファイルの各圧縮ブロックは、そのブロックの圧縮に使用されたハフマン・コード・テーブルが出力ブロックに含まれているか、或いは出力ブロックに含まれていないかを示すビットをヘッダーに含んでいる。ハフマン・コード・テーブルが含まれていない場合、ハフマン・コード・テーブルは暗示され、DEFLATE仕様のセクション3.2.6で規定される。DEFLATE仕様では、前者(ハフマン・コード・テーブルが含まれる)は動的ハフマン・コードでの圧縮と呼ばれ、後者(ハフマン・コード・テーブルが暗示される)は固定ハフマン・コードでの圧縮と呼ばれる。動的なアプローチには、圧縮ファイルがハフマン・コード・テーブルの表現を含まなければならないという欠点があり、ハフマン・コード・テーブルが出力ブロック内の空間を占め、このことは出力ファイルを小さくするという目的に反する働きをする。したがって、固定されたアプローチは、小さい入力ファイルに対しては、場合によっては動的なアプローチが生成するよりも小さい出力ファイルを生成することができる。
しかし、動的なアプローチには、DEFLATE仕様の固定ハフマン・コード・テーブルを使用して得られるよりも優れたハフマン・コーディングが得られる可能性が高くなるように、ハフマン・コードをアルファベットのシンボルに割り当てることができるという利点がある。この場合、優れたハフマン・コーディングとは、動的ハフマン・コード・テーブルが、固定ハフマン・コード・テーブルが生成する場合よりも高い圧縮率でLZ77出力ストリームを生成するということである。これは、固定ハフマン・コード・テーブルが汎用的であるゆえに、その確率の推定又は相対的な頻度があまり適切でない可能性があるからであり、固定ハフマン・コード・テーブルが特定の特徴に合わせて調整されないため、2つのアルファベットのさまざまなシンボルがハフマン圧縮されたLZ77出力ストリームに出現することになる。前述したように、動的ハフマン・コード・テーブルは、LZ77出力ストリーム内により頻繁に出現するアルファベットのシンボルにより短いコードを割り当て、あまり頻繁に出現しないシンボルにより長いコードを割り当てて、入力ブロックの高い圧縮率を実現することができる。従来(例えば、gzip又はzlibによって実行されているように)、入力ブロックを圧縮して、動的ハフマン・コード・テーブルを使用してDEFLATE仕様に従う(可能であれば)より小さい出力ブロックを作り出すための処理は、以下のように3つのステップの処理を備える。
第1ステップで、処理は、入力ブロックに対してLZ77圧縮を実行して、LZ77出力ストリームと呼ばれるトークン(リテラルとバック・ポインタ)のストリームを作り出す。このステップは、入力ブロックのスキャンとも呼ばれ、文字列の一致について入力ブロックを後方に検索することを含む。入力ブロックをスキャンする間、プログラムは、トークンのストリームに基づいて2つのヒストグラムをさらに作り出す。一方のヒストグラムは、リテラル/長さのアルファベットにおける各シンボルについてのエントリを含み、他方のヒストグラムは、距離のアルファベットにおける各シンボルについてのエントリを含む。ヒストグラム内の各エントリは、シンボルがLZ77トークン出力ストリームに現れた回数に関連付けられた頻度を明示する。バック・ポインタのトークンには、リテラル/長さのアルファベットの長さシンボルと距離のアルファベットの距離シンボルとの、2つのシンボルが関係付けられていることに注意する。
第2ステップで、処理は、処理の第1ステップで作り出された対応するヒストグラムを使用して、リテラル/長さハフマン・コード・テーブルと距離ハフマン・コード・テーブルを構築する。
第3ステップで、処理は、処理の第2ステップの間に構築されたハフマン・コード・テーブルを使用してLZ77トークン出力ストリームをハフマン・エンコードして、圧縮された出力ブロックを作り出す。この出力ブロックは、可変長ハフマン・コードを含むビット列である。バック・ポインタの長さを指定する出力ブロック内のハフマン・コードの場合、バック・ポインタの距離を指定するハフマン・コードがその後に続く。
動的ハフマン・コード・テーブルを使用してDEFLATE方式入力ブロックを圧縮するための、前述の3つのステップの処理における従来の欠点は、ステップが逐次的に実行されることである。つまり、ハフマン・コード・テーブルが構築される(第2ステップ)まで、ハフマン・エンコーディング(第3ステップ)は実行されることが不可能であり、ヒストグラムが(第1ステップの間に)完全に作り出されるまで、ハフマン・コード・テーブルは構築されない(第2ステップ)。
しかし、第1ステップと第3ステップは、例えば、固定ハフマン・コード・テーブルが使用されているときに実行されることが可能であるため、並行して実行されることが可能である。本発明者らは、ある観察を行うことにより、動的ハフマン・コード・テーブルを使用することによって得られる所望の圧縮率の改善を提供しながら、動的ハフマン・コード・テーブルを使用することに伴う速度の低下を防ぐハードウェア・データ圧縮器(compressor)を発明することができた。本発明者らは、入力ブロックの初期部分のみがスキャンされた後のヒストグラムを調べ、該ヒストグラムを、入力ブロック全体がスキャンされた後のヒストグラムと比較した。多くの場合、この比較によって、アルファベットのさまざまなシンボルの間の相対的な頻度に関して、時間におけるこれら2つの事例での頻度に、大きな差がないことが明らかであるのが観察された。つまり、多くの場合、入力ブロックの残りの部分がスキャンされた後のヒストグラムにおける相対的頻度は、最初の部分のみがスキャンされた後の相対的頻度とほとんど変わらない。例えば、入力ブロックの10%のみがスキャンされた後、「A」の頻度が6、「B」の頻度が3、「C」の頻度が4であり得、一方、入力ブロック全体がスキャンされた後に、「A」の頻度が62、「B」の頻度が31、「C」の頻度が44であり得る。相対的な観点からは、入力ブロックの10%のみがスキャンされた後の頻度と入力ブロック全体がスキャンされた後の頻度との間に差異はない。
このことは、ハフマン・コード・テーブルがアルファベットのシンボルの絶対的頻度値ではなく相対的頻度に基づいて作成されることが可能であるため、有益な観察である。つまり、前述したように、より頻度の高いシンボルに、より短いコードを使用することによって入力ブロックの圧縮を最適化するために、アルファベットのシンボルの相対的頻度が高いほど、それに割り当てられるハフマン・コードは短くなる(すなわち、ビット数が少なくなる)。
この観察に基づき、ハードウェア・データ圧縮器の実施形態は、入力ブロックの最初の部分のみがスキャンされた後に、ヒストグラムの更新を停止し、この「不完全な」ヒストグラムを使用してハフマン・コード・テーブル(本明細書では、「ダイナミック−プライム」ハフマン・コード・テーブルと呼ばれる)を構築し、その後、入力ブロックの残りの部分のスキャンと並行して、ダイナミック−プライム・ハフマン・コード・テーブルの使用を開始し、LZ77出力トークン・ストリームをエンコードすると説明される。これによって、ハードウェア・データ圧縮器のハフマン・コーディング・エンジンは、そのハフマン・コーディングを、LZ77圧縮エンジンによる入力ブロックの残りの部分のスキャンと重複させることができ、そのため、ハフマン・コーディング時間の、全部ではないにしても少なくともいくらかが、LZ77圧縮時間の背後に隠れる。ハフマン・コーディングにかかる時間が、通常は、LZ77圧縮に関連する入力ブロックのスキャンにかかる時間よりも少ないことを考えると、入力スキャンの間にハフマン・コード・テーブルが構築される時点に依存して、ハフマン・コーディング時間が入力ブロック圧縮処理に対して加算する時間は、無視できる量である場合がある。
さらに、本発明者らは、各シンボルの出現頻度に基づくヒストグラムのソート(効率的なハフマン・コード・テーブルの構築に必要とされる)が時間のかかる処理であり、図9に示すように、圧縮処理のクリティカル・パスにあり、したがって合計圧縮時間を加算する要因になっていることを観察した。有利なことに、本実施形態は、頻度によるシンボル・リストのソートが入力ブロックのスキャンと同時にインクリメンタルに、好ましくは各シンボルがLZ77エンジンによって作り出されるときに別個のハードウェア・エンジンによって(例えば、図2A及び2Bを参照)実行されて、ソート時間を入力ブロックのスキャン時間の背後に隠して、合計圧縮時間を減少させると説明される。本発明者らの観察によれば、各シンボルがLZ77によって生成されるとき、シンボルの頻度値は1ずつだけ変更され、ソート済みリスト内のシンボルの場所を変更する必要はない可能性が高く、変更する必要がある場合でも、シンボルの場所を短い距離ずつ変更するだけで済み、このことは極めて高速に実行することができる可能性が高く、ソート・エンジンは、上記観察からの恩恵を有利に受ける。特に、ソート済みリスト内のシンボルの場所を変更するために必要な時間は、LZ77エンジンがターゲット文字列の一致を検索し及び検出するために必要な時間よりも少なくなる可能性が非常に高い。さらに有利なことに、インクリメンタル且つ同時に行われるシンボル・リストのソート・メカニズムは、ダイナミック−プライム・ハフマン・テーブルの実施形態と組み合わせて採用されることが可能である。
ハードウェア・データ圧縮器
ここで図1を参照すると、ハードウェア・データ圧縮器100を表すブロック図が示されている。ハードウェア・データ圧縮器100は、入力ブロック・メモリ101と、圧縮エンジン102(例えば、LZ77エンジン)と、ハッシュ・メモリ103と、ソート・エンジン104と、バック・ポインタ及びフラグ・メモリ105と、ハフマン・コード・テーブル構築エンジン106と、頻度テーブル、シンボルのソート済みリスト、及びハフマン・コード・テーブルを格納するテーブル・メモリ107と、ハフマン・エンコーディング・エンジン108と、出力メモリ109とを含む。圧縮エンジン102、ソート・エンジン104、ハフマン・コード・テーブル構築エンジン106、及びハフマン・エンコーディング・エンジン108は、ハードウェア・エンジンである。ハードウェア・エンジンはハードウェアであり、ハードウェア・ステート・マシンを含めて、ハードウェアの組み合わせ論理及び順序論理を含むことができる。ハードウェア・エンジンは、メモリに格納された命令を取得して該命令を実行するプログラム可能なプロセッサとは区別可能である。しかし、ハードウェア・エンジンは、1つ又は複数のメモリから入力としてデータを読み出し、1つ又は複数のメモリに出力としてデータを書き込むことができる。
入力ブロック・メモリ101は、圧縮されるべき複数の文字から成る入力ブロックを保持する。一実施形態では、入力ブロック・メモリ101は32KBであり、別の実施形態では、入力ブロック・メモリ101は16KBであるが、他の実施形態が企図される。通常、複数の文字から成る入力ブロックは、画像ファイル(例えば、JPG、TIFF)、オーディオ・ファイル(例えば、AIFF、WAV)、テキスト・ファイル、スプレッドシート、ワード・プロセッサやプレゼンテーション・アプリケーションによって生成されたファイル、又はその他の種類のファイル(例えば、PDF)などの、圧縮されるべき入力ファイルの複数の文字の一部である。入力ブロックの各文字は、1バイト・データであることが好ましい。入力ブロック・メモリ101は、入力ブロックを圧縮エンジン102及びハフマン・エンコーディング・エンジン108に提供する。一実施形態では、入力ブロック・メモリ101は、実施形態における競合を減らすようにデュアルポート・メモリであり、圧縮エンジン102は、入力ブロック・メモリ101にアクセスして入力ブロックをスキャンして(例えば、現在の検索位置で文字列を取得し、入力ブロック内の以前の部分との一致を検索して)圧縮を実行し(例えば、一致する文字列を置換するためのバック・ポインタを作り出す)、同時に、ハフマン・エンコーディング・エンジン108は、入力ブロック・メモリ101にアクセスして出力トークン・ストリームのリテラル・シンボル(バック・ポインタによって置換されない入力ブロックの文字)をハフマン・エンコードする。一実施形態では、入力ブロックは、システム・メモリから入力ブロック・メモリ101にロードされる。
圧縮エンジン102は、入力ブロックの文字の文字列を、入力ブロック内の以前の文字列へのバック・ポインタで置換することによって、入力ブロックを圧縮する。以前の文字列は、バック・ポインタによって置換される文字列に一致する。圧縮エンジン102は、好ましくは、LZ77エンジン102である。LZ77エンジン102は、論文「A Universal Algorithm for Sequential Data Compression」(Ziv J.、Lempel A.著、情報理論に関するIEEEトランザクション、第23巻3号、pp.337−343)に記載されたアルゴリズム又はその変形を使用する。ただし、圧縮エンジン102が他の文字列置換可逆圧縮アルゴリズムを使用してバック・ポインタを生成する他の実施形態が企図される。
好ましくは、LZ77エンジン102は、バック・ポインタを生成し、バック・ポインタ・メモリ105に格納する。一実施形態では、LZ77エンジン102は、バック・ポインタ・メモリ105内にフラグの配列を維持する。一実施形態では、各フラグは、入力ブロック内の1文字に対応する単一ビットである(例えば、16K文字の入力ブロックに対して16Kビットのフラグが存在する)。フラグがtrue値である場合、このことは、バック・ポインタ・メモリ105に格納されたバック・ポインタが、フラグ配列内のそのフラグの位置に対応する入力ブロック内の位置で始まる文字列を置換したことを示す。例えば、フラグ配列のインデックス3742のフラグがtrueである場合、LZ77エンジン102は、入力ブロック内の位置3742で始まる文字列を置換するバック・ポインタを生成している。そうでない場合(フラグがfalseの場合)、そのフラグのインデックスに対応する入力ブロック内の位置の文字は、LZ77エンジン102の出力トークンのストリームの一部である「リテラル」文字と見なされる。リテラルは、その後にハフマン・エンコーディング・エンジン108によってハフマン・エンコードされ、出力メモリ109に格納されることになるシンボルである。
下でより詳細に説明されているように、好ましくは、LZ77エンジン102は、一致する文字列の検索時間を減らすために、ハッシュ・テーブル及びハッシュ技術を採用する。ハッシュ・テーブルは、ハッシュ・メモリ103に格納される。有利なことに、一実施形態では、下でより詳細に説明されているように、LZ77エンジン102は、圧縮速度を上げるために2つのハッシュ・テーブルを採用する。
テーブル・メモリ107は、LZ77エンジン102、ソート・エンジン104、ハフマン・コード・テーブル構築エンジン106、及びハフマン・エンコーディング・エンジン108によってアクセス可能である。テーブル・メモリ107内の頻度テーブル(その一例が、図4の要素401として示される)は、頻度(図4の要素402)、又は、LZ77エンジン102の出力トークンのストリーム内で各シンボルが出現した回数を保持する。一実施形態では、LZ77エンジン102が、頻度テーブル401の頻度値402を維持する。代替の実施形態では、ソート・エンジン104が、LZ77エンジン102によって生成されたトークン212に応答して、頻度テーブル401の頻度値402を維持する。別の代替の実施形態では、ハフマン・コード・テーブル構築エンジン106が、LZ77エンジン102によって生成されたトークン212に応答して、頻度テーブル401の頻度値402を維持する。下でより詳細に説明されているように、ソート・エンジン104は、シンボルのソート済みリスト(その一例が、図4のソート済みリスト403として示される)を、シンボルの頻度に従って(例えば、図4の頻度テーブル401のエントリのソート済みインデックス・フィールド404を使用して)維持する。さらに、ハフマン・コード・テーブル構築エンジン106は、頻度でソートされたシンボルのソート済みリストを使用して、ハフマン・コード・テーブルを構築する。このハフマン・コード・テーブルは、ハフマン・エンコーディング・エンジン108によって、LZ77エンジン102の出力ストリームのトークンに関連付けられたシンボルをハフマン・エンコードして出力メモリ109に格納するために使用される。
下でより詳細に説明されているように、好ましくは、ハフマン・エンコーディング・エンジン108は2つのハフマン・コード・テーブル、リテラル及び長さシンボルについて1つと距離シンボルについて1つとを採用し、したがって、2つの対応する頻度テーブル及びソート済みリストが維持され、これらから2つのハフマン・コード・テーブルが構築される。一実施形態では、ハフマン・コード・テーブル構築エンジン106は、DEFLATE仕様などで使用される、良く知られた標準的なハフマン・エンコーディング処理に従って、ハフマン・コード・テーブルを構築する。好ましくは、リテラル・シンボルをハフマン・エンコードすることは、リテラル・シンボル値(例えば、図11Aのシンボル値406、又は図11Bの頻度テーブル401へのインデックス)に関連付けられたハフマン・コード(例えば、図11A及び11Bのハフマン・コード1108)を出力することを意味し、バック・ポインタの長さをハフマン・エンコードすることは、長さシンボルの値に関連付けられたハフマン・コードを出力し、その長さシンボルの長さの範囲が、バック・ポインタの長さに加えて、バック・ポインタの長さの指定に使用される任意の追加ビット(extra bits)(例えば、DEFLATE仕様のセクション3.2.5に記載された、下の表1で規定される)を包含することを意味し、バック・ポインタの距離をハフマン・エンコードすることは、距離シンボルの値に関連付けられたハフマン・コードを出力し、その距離シンボルの距離の範囲が、バック・ポインタの距離に加えて、バック・ポインタの距離の指定に使用される任意の追加ビット(例えば、DEFLATE仕様のセクション3.2.5に記載された、下の表2で規定される)を包含することを意味する。「コード」という用語が下の表1に含まれているのは、「コード」という用語がDEFLATE仕様の表で使用されているからであるということが理解されるべきである。ただし、表1の「コード」列の値は、例えば図11A及び11Bのハフマン・コード1108などの、ハフマン・コードではない。むしろ、「コード」列の値は、例えば、図4の実施形態のシンボル値406に対応し、この値は、図4の頻度テーブル401へのインデックスの値でもある。このことは、距離シンボルに関する表2に対しても当てはまる。
ソート・エンジン104を含まず、代わりに、LZ77エンジン102が頻度テーブルの更新を完了した後に、ハフマン・コード・テーブル構築エンジン106が頻度テーブルのシンボルのソートを実行する実施形態が企図される。通常、LZ77エンジン102は、入力ブロック全体をスキャンした後に、頻度テーブルの更新を停止する。しかし、下で説明される実施形態では、LZ77エンジン102が、入力ブロックの初期部分をスキャンした後に、頻度テーブルの更新を有利に停止し、その時点でハフマン・コード・テーブル構築エンジン106がハフマン・コード・テーブルを構築する。このハフマン・コード・テーブルは、本明細書では、「ダイナミック−プライム」ハフマン・コード・テーブルと呼ばれる。
入力ブロックのスキャンと同時のソート済みシンボル・リストの維持
ここで図2Aを参照すると、図1のハードウェア圧縮器100の一部を表すブロック図が示されている。図1のLZ77エンジン102は、ソート・エンジン104に対してトークン212を生成する。トークン212は、バック・ポインタ又はリテラルの文字列(単一のリテラル文字になる場合もある)のいずれかの表現になる。一実施形態では、トークン212は、リテラルの文字列の位置についての入力ブロック・メモリ101へのポインタ又はインデックスである。このような実施形態では、入力ブロック・メモリ101は、ソート・エンジン104によってアクセス可能である。代替の実施形態では、トークン212は、リテラル自体の文字列、例えば、文字列の文字の値である。一実施形態では、トークン212は、バック・ポインタの位置についてのポインタ・メモリ105へのポインタ又はインデックスである。このような実施形態では、ポインタ・メモリ105は、ソート・エンジン104によってアクセス可能である。代替の実施形態では、トークン212は、バック・ポインタ自体、例えば、バック・ポインタの長さ及び距離の値である。特に図3に関して下でより詳細に説明されているように、ソート・エンジン104は、テーブル・メモリ107内の頻度テーブル401及びソート済みリスト403の更新の進行状況に基づいて、LZ77エンジン102へのレディ信号214を発生させる。
図3〜8の検討から推測できるように、あるシンボルの頻度がソート済みリスト内で該シンボルの上にある他の複数のシンボルの頻度と同じであり、したがって、上記シンボルの頻度がインクリメントされたときにソート・エンジン104がシンボルをリスト403内の正しくソートされた位置へ到達させるように複数回の交換を実行する必要がある、異常な状態が生じる可能性がある。さらに、インクリメントされたシンボルの頻度は、その上にある、より後の辞書式順序の値を持つ複数のシンボルの頻度に等しくなる可能性があり、したがって、シンボルの頻度がインクリメントされたとき、ソート・エンジン104は、シンボルをリスト403内の正しくソートされた位置へ到達させるように複数回の交換を実行する必要がある。ソート・エンジン104がビジーになり、トークン212をLZ77エンジン102から受信できない場合、入力ブロックの圧縮を実行するために必要な時間が増加する可能性がある。
一般的に言えば、シンボルの頻度の分布が相対的に均一な場合に、このような異常な状態が生じやすくなる。この状態は、すべての頻度がゼロに初期化されているときに、入力バッファのスキャンの初期に発生しやすい。頻度が等しくない値に初期化される、図14A〜14C及び図16に関して下で説明されているような実施形態は、異常な状態が発生する見込みを減らす長所を有し得ることに、注目するべきである。
一実施形態では、ハードウェア・データ圧縮器100は、LZ77圧縮エンジン102とソート・エンジン104との間に短期の先入先出(first−in first−out:FIFO)メモリを含み、このFIFOメモリは、LZ77圧縮エンジン102からソート・エンジン104に提供されるトークン212をバッファリングして、必要な場合に異常な状態の影響を減らすか、場合によっては除去する。FIFOによるフル・フラグの出力は、LZ77圧縮エンジン102に対するレディ信号214としての役割を果たす。
ここで図2Bを参照すると、図2AのLZ77エンジン102及びソート・エンジン104の動作を表すタイミング図が示されている。上側部分はLZ77エンジン102の動作を示し、下側部分はソート・エンジン104の動作を示している。時間は、左から右に進んでいる。図に示されている時間は単位を持たず、相対的な時間を表すために使用されている。しかし、上記時間は、クロック・サイクル、ナノ秒、又はその他の関連する時間単位の代表であり得る。
図に示されているように、時間0で、LZ77エンジン102が、(例えば、図3のブロック302でのように)現在の検索位置での入力ブロックのスキャンを開始して文字列の一致を検索し、時間6で、トークンNで示されるトークン212をソート・エンジン104に出力する。それに応答して、ソート・エンジン104は、(例えば、図3のブロック316でのように)トークンNに関連付けられた各シンボルの頻度をインクリメントし、シンボルのソート済みリスト(例えば、図4のソート済みリスト403)を再ソートして、シンボル間における頻度(及び辞書式順序)でソートされた順序を維持し、時間12で終了する。その後、LZ77エンジン102は、次の検索を終了し、時間18でトークンN+1を出力する。それに応答して、ソート・エンジン104は、トークンN+1に関連付けられた各シンボルの頻度をインクリメントし、シンボルのソート済みリストを再ソートして、頻度でソートされた順序を維持し、時間25で終了する。その後、LZ77エンジン102は、次の検索を終了し、時間38でトークンN+2を出力する。それに応答して、ソート・エンジン104は、トークンN+2に関連付けられた各シンボルの頻度をインクリメントし、シンボルのソート済みリストを再ソートして、ソートされた順序を維持し、時間47で終了する。その前に、LZ77エンジン102は、次の検索を終了し、トークンN+3を出力する。この場合、レディ信号214がLZ77エンジン102をストールさせ、ソート・エンジン104のソート完了を待機することになる(ただし、前述したように、実施形態にFIFOが存在し、且つFIFOがフルではない場合を除く)。
図2Bに示されているように、有利なことに、LZ77エンジン102が入力ブロックをスキャンすることと同時に、ソート・エンジン104は頻度でソートされたシンボルのリストをインクリメンタルに持続させ、したがって、シンボルのソート済みリストを維持するために必要な時間は、本明細書でより詳細に説明されているように、入力ブロックのスキャン時間の背後に隠れる。
ここで図3を参照すると、図2AのLZ77エンジン102及びソート・エンジン104の動作を表すフローチャートが示されている。図3において、LZ77エンジン102はブロック302〜308における動作を実行し、ソート・エンジン104はブロック312〜318における動作を実行している。フローは、ブロック302から始まる。
302で、LZ77エンジン102は入力ブロックをスキャンし、入力ブロック内の現在の検索ターゲット位置における文字列の一致を検索する。フローは、判定ブロック304に進む。
判定ブロック304で、LZ77エンジン102はレディ信号214を調べて、ソート・エンジン104がLZ77エンジン102からトークン212を受信する準備ができているかを決定する。準備ができている場合、フローはブロック306に進み、準備ができていない場合、ソート・エンジン104が準備ができるまでは、フローは判定ブロック304に戻る。
ブロック306で、LZ77エンジン102はソート・エンジン104に対してトークン212を生成する。フローはLZ77エンジン102に関するブロック308に進み、同時に、フローはソート・エンジン104に関する判定ブロック312に進む。
ブロック308で、LZ77エンジン102は現在の検索ターゲット位置を更新する。フローはLZ77エンジン102に関するブロック302に戻って、ブロック終結文字に直面するまで次の文字列を検索する。
判定ブロック312で、ソート・エンジン104は、LZ77エンジン102がソート・エンジン104のためにトークン212を生成したかどうかを決定する。生成していた場合、フローはブロック314に進み、生成していない場合、LZ77エンジン102がトークン212を生成するまでは、フローは判定ブロック312に戻る。
ブロック314で、ソート・エンジン104は、レディ信号214上でfalse値を出力する。フローはブロック316に進む。
ブロック316で、LZ77エンジン102から受信されたトークン212の各シンボルについて、ソート・エンジン104は、図5に関して下でより詳細に説明されているように、シンボルの頻度(例えば、図4の402)をインクリメントし、シンボルの出現頻度及び辞書式順序に従ってソート済みリスト(例えば、図4の403)を維持する。フローはブロック318に進む。
ブロック318で、ソート・エンジン104は、レディ信号214上でtrue値を出力する。フローは判定ブロック312に戻る。
前述したように、通常、ソート・エンジン104は、LZ77エンジン102がブロック302における動作を実行するよりも少ない時間において、ブロック316における動作を実行する。その結果、LZ77エンジン102によって生成されたトークンに応答してブロック316でソート・エンジン104がシンボルのソート済みリストを維持するのに必要とされる時間は、通常、ブロック302でLZ77エンジン102が次のトークンを生成するのに必要とされる時間の背後に有利に隠れる。これは、本発明者らの観察によれば、シンボルの頻度値は1ずつしか変化せず、その結果、ソート済みシンボル・リスト内でのシンボルの場所を変更する必要がない可能性が非常に高く、変更する必要がある場合でも、ソート済みリスト内のシンボルの場所を短い距離ずつ変更するだけで済む可能性が非常に高く、上記のことを、ソート・エンジン104は通常、LZ77エンジン102の文字列検索よりも速く実行することができるからである。
ここで図4を参照すると、図1のソート・エンジン104によって使用するための頻度テーブル401、ソート済みリスト403、及びテール・ポインタ407を表すブロック図が示されている。頻度テーブル401は、各々が2つのフィールドを有するエントリの配列であり、2つのフィールドとは、頻度フィールド402及びソート済みインデックス・フィールド404である。各エントリは、図1のハフマン・エンコーディング・エンジン108によってエンコードされるべきシンボルのシンボル空間のうちの異なるシンボルに関連付けられている。シンボルの値は、頻度テーブル401へのインデックスである。シンボルの頻度402は、そのシンボルがLZ77エンジン102の出力ストリームに現れるたびに更新される。図4の実施形態例では、シンボル空間は、頻度テーブル401のインデックスを指す(index into)値0〜285を含む。シンボル空間の値0〜285は、DEFLATE仕様で規定されたリテラル及び長さシンボルに対応する。ただし、他のシンボル・アルファベットが採用され、(例えば、図2Bに示されるように)ハードウェア圧縮エンジンが入力ブロックをスキャンすると同時にハードウェア・ソート・エンジンが頻度でソートされたシンボルのリストをインクリメンタルに持続させる上記記載のアプローチを使用する、他の実施形態が企図される。図5に関して下でより詳細に説明されているように、シンボル値によってインデックスを指された頻度テーブル401内のエントリのソート済みインデックス404は、ソート・エンジン104がシンボル値406をソートした、ソート済みリスト403内のエントリを指し示す。
ソート済みリスト403は、頻度テーブル401と同じ数のエントリを含む配列である。ソート済みリスト403の先頭のエントリ、エントリ0は、LZ77エンジン102の出力ストリーム内で最も頻繁に出現したシンボルのシンボル値406を保持し、エントリ1は、LZ77エンジン102の出力ストリーム内で次に最も頻繁に出現したシンボルのシンボル値406を保持する、などのようになる。同じ回数出現したシンボルは、辞書式順序で現れ、すなわち、より小さいシンボル値406は、リスト403内で、より大きいシンボル値406よりも高いところにソートされる。したがって、ソート済みリスト403へのインデックスは、シンボルの出現頻度及び辞書式順序の値による順序を示し、該シンボルの値406は、ソート済みリスト403のインデックスを指されたエントリに格納される。
有利なことに、ソート済みリスト403は、本質的に頻度テーブル401を逆に指している。つまり、ソート済みリスト403のエントリ内のシンボル値406は、ソート済みリスト403のエントリ内にあるシンボルについて、頻度テーブル401へのインデックスである。したがって、現在のシンボルの値から始めて(すなわち、該シンボルの頻度402がインクリメントされている)、現在のシンボルの1エントリ上のシンボルの頻度402は、ソート済みリスト403の1つ上のエントリ内のシンボル値406を使用して頻度テーブル401のインデックスを指すことによって、頻度テーブル401から取得されることが可能である。これにより、2つの頻度402の比較が(例えば、図5のブロック512及び516で)実行されて、(例えば、図5のブロック514及び522で)現在のシンボルがソート済みリスト403内で上に移動される必要があるかどうかを決定することができる。
テール・ポインタ407は、ソート済みリスト403内で使用可能な次のエントリを指し示し、そのエントリの位置に、LZ77エンジン102の出力ストリーム内で新しく現れる次のシンボルが配置される。テール・ポインタ407におけるエントリと該エントリの下のエントリとは、空である。
1つの頻度テーブル401と1つのソート済みリスト403のみが(例えば、リテラル及び長さに対して)示されているが、距離に対しては別の頻度テーブル及びソート済みリストが維持されることが理解されるべきである。DEFLATE仕様の実施形態では、距離の頻度テーブル401及び距離のソート済みリスト403は、リテラル及び長さに対して示されている286個のエントリではなく、それぞれ30個のエントリ(0〜29としてインデックスを指される)を有する。
図4では、頻度テーブル401とソート済みリスト403の使用方法を説明するために、さまざまな値の例が示されている。例えば、頻度テーブル401の頻度のエントリ1は、180の頻度402及び24のソート済みインデックス404を有し、このインデックスは、ソート済みリスト403のエントリ24を指し示し、このエントリはシンボル値1を有している。同様に、頻度テーブル401のエントリ3は、20の頻度402及び137のソート済みインデックス404を有し、このインデックスは、ソート済みリスト403のエントリ137を指し示し、このエントリはシンボル値3を有している。頻度テーブル401のエントリ27は、180の頻度402及び25のソート済みインデックス404を有し、このインデックスは、ソート済みリスト403のエントリ25を指し示し、このエントリはシンボル値27を有している。頻度テーブル401のエントリ29は、181の頻度402及び23のソート済みインデックス404を有し、このインデックスは、ソート済みリスト403のエントリ23を指し示し、このエントリはシンボル値29を有している。頻度テーブル401のエントリ279は、1000の頻度402及び1のソート済みインデックス404を有し、このインデックスは、ソート済みリスト403のエントリを指し示し、このエントリはシンボル値279を有している。これらの値は、図5に従ってソート・エンジン104の動作を示すために、図6〜8において説明の目的で使用される。
ここで図5を参照すると、図3のブロック316の実施形態による図1のソート・エンジン104の動作を表すフローチャートが示されている。以下の図5の説明では、ソート・エンジン104の動作を説明するために擬似コードが提供されているが、ソート・エンジン104はソフトウェアというよりも、ハードウェアで表現されたさまざまな動作を実行するハードウェア・エンジンであるということが理解されるべきである。フローは、ブロック502から始まる。
ブロック502で、ソート・エンジン104はLZ77エンジン102からトークン212を受け取り、トークン212に関連付けられたシンボルを決定する。図5は、トークン212に関連付けられた1つのシンボルに関するソート・エンジン104の動作を表しているが、ソート・エンジン104は、すべてのシンボルに対して動作を実行する。前述したように、トークン212がバック・ポインタである場合、トークン212は2つの関連付けられたシンボル、すなわち、バック・ポインタの長さ及び距離を有する。一方、トークン212がリテラル文字列である場合、トークン212は、その文字列の文字の数と同じ数の関連付けられたシンボルを有し、該シンボルは、文字列の文字値である。例えば、15個の文字から成るASCIIリテラル文字列のトークン212「This is the day」は、15個のシンボル、すなわち、「T」、「h」、「i」、「s」、「 」、「i」、「s」、「 」、「t」、「h」、「e」、「 」、「d」、「a」、「y」、又は数値的に、84、104、105、115、32、105、115、32、116、104、101、32、100、97、121を有する。フローは、判定ブロック504に進む。次の擬似コードは、ブロック502で実行される動作を示している。
increment freq_tbl[this_symbol_val].freq
判定ブロック504で、ソート・エンジン104は、これがシンボルの最初の出現であるかどうかを、好ましくは頻度テーブル401内のシンボルの頻度402の値を調べることによって決定する。これが最初の出現である場合、フローはブロック506に進み、そうでない場合、フローは判定ブロック508に進む。次の擬似コードは、ブロック504で実行される動作を示している。
if (freq_tbl[this_symbol_val].freq == 1)
ブロック506で、ソート・エンジン104はシンボルをソート済みリスト403の末尾に(例えば、テール・ポインタ407によって指し示されたエントリに)挿入し、テール・ポインタ407を更新する(例えば、インクリメントする)。フローはブロック506で終了する。次の擬似コードは、ブロック506で実行される動作を示している。
freq_tbl[this_symbol_val].sorted_idx = tail_ptr
sorted_list[tail_ptr] = this_symbol_val
increment tail_ptr
判定ブロック508で、ソート・エンジン104は、シンボルがソート済みリスト403の先頭にあるかどうかを決定する。先頭にある場合、フローが終了し、先頭にない場合、フローは判定ブロック512に進む。次の擬似コードは、ブロック508で実行される動作を示している。
if (freq_tbl[this_symbol_val].sorted_idx == 0)
判定ブロック512で、ソート・エンジン104は、シンボルの頻度402がソート済みリスト403内のその上にあるシンボルの頻度402よりも大きいかどうかを決定する。大きい場合、フローはブロック514に進み、そうでない場合、フローは判定ブロック516に進む。次の擬似コードは、ブロック512で実行される動作を示している。
X = freq_tbl[this_symbol_val].freq
this_sorted_idx = freq_tbl[this_symbol_val].sorted_idx
above_symbol_val = sorted_list[this_sorted_idx − 1]
Y = freq_tbl[above_symbol_val].freq
if (X > Y)
ブロック514で、ソート・エンジン104は、シンボルをソート済みリスト403内で上に移動する。つまり、ソート・エンジン104は、ソート済みリスト403内のシンボルの場所と、ソート済みリスト403内の上にあるエントリ内のシンボルの場所を交換する。これによって、ソート済みリスト403の関連するエントリ内のシンボル値406が更新されるだけでなく、頻度テーブル401の関連するエントリのソート済みインデックス404の値も更新される。フローは、ブロック514から判定ブロック508に戻り、シンボルをソート済みリスト403内で再び上に移動する必要があるかどうかを決定する。次の擬似コードは、ブロック514及びブロック522で実行される動作を示している。
decrement freq_tbl[this_symbol_val].sorted_idx
increment freq_tbl[above_symbol_val].sorted_idx
sorted_list[this_sorted_idx] = above_symbol_val
sorted_list[this_sorted_idx − 1] = this_symbol_val
判定ブロック516で、ソート・エンジン104は、シンボルの頻度402がソート済みリスト403内のその上にあるシンボルの頻度402に等しいかどうかを決定する。等しい場合、フローは判定ブロック518に進み、そうでない場合、フローは終了する。次の擬似コードは、ブロック516で実行される動作を示している。
X = freq_tbl[this_symbol_val].freq
this_sorted_idx = freq_tbl[this_symbol_val].sorted_idx
above_symbol_val = sorted_list[this_sorted_idx − 1]
Y = freq_tbl[above_symbol_val].freq
if (X == Y)
判定ブロック518で、ソート・エンジン104は、シンボルの値の辞書式順序が、ソート済みリスト403内のその上にあるシンボルの値の辞書式順序よりも先かどうか(つまり、値が小さいかどうか)を決定する。小さい場合、フローは判定ブロック522に進み、そうでない場合、フローは終了する。次の擬似コードは、ブロック518で実行される動作を示している。
if (this_symbol_val < sorted_list[this_symbol_val−1])
判定ブロック522で、ソート・エンジン104は、上のブロック514に関して説明したのと同様の方法で、シンボルをソート済みリスト403内で上に移動する。フローは、ブロック522から判定ブロック516に戻って、シンボルをソート済みリスト403内で再び上に移動する必要があるかどうかを決定する。
ここで図6を参照すると、ソート・エンジン104によって更新された図4の頻度テーブル401、ソート済みリスト403、及びテール・ポインタ407を表すブロック図が示されている。図6は、図4の頻度テーブル401及びソート済みリスト403の、ソート・エンジン104が受信したシンボル27を処理した後の状態を表している。具体的には、ソート・エンジン104は、頻度テーブル401のインデックス27にある頻度402を、図5のブロック502に従って180から181にインクリメントしている。さらにソート・エンジン104は、図5の判定ブロック512で、シンボル27の頻度402(181)が、図4のソート済みリスト403内のその上にあったシンボル(シンボル1)の頻度402(シンボル1は180の頻度を有する)よりも大きいと決定している。その結果、図5のブロック514に従い、ソート・エンジン104はソート済みリスト403内のシンボル27の位置とシンボル1の位置を交換している。これによって、エントリ24のシンボル値406が1から27に変更され、エントリ25のシンボル値406が27から1に変更されている。さらに、これによってソート済みインデックス404の各値が交換されており、好ましくはソート・エンジン104によって、シンボル1のソート済みインデックス404が24から25にインクリメントされ、シンボル27のソート済みインデックス404が25から24にデクリメントされる。これらの変更は、図6で、変更された値を含む灰色の長方形と、変更されたソート済みインデックス404のポインタ値に対応する破線矢印で強調表示されている。
ここで図7を参照すると、ソート・エンジン104によって更新された図6の頻度テーブル401、ソート済みリスト403、及びテール・ポインタ407を表すブロック図が示されている。図7は、図6の頻度テーブル401及びソート済みリスト403の、ソート・エンジン104が受信したシンボル27をさらに処理した後の状態を表している。具体的には、ソート・エンジン104は、図5の判定ブロック516で、シンボル27の頻度402(181)が、図6のソート済みリスト403内のその上にあったシンボル(シンボル29)の頻度402(シンボル29もまた181の頻度を有する)に等しいと決定しており、また、ソート・エンジン104は、判定ブロック518で、シンボル27の値がソート済みリスト403内のその上にあるシンボル29の値よりも辞書的に前であると決定している。その結果、図5のブロック522に従い、ソート・エンジン104はソート済みリスト403内のシンボル27の位置とシンボル29の位置を交換している。これによって、エントリ23のシンボル値406が29から27に変更され、エントリ24のシンボル値406が27から29に変更されている。さらに、これによってソート済みインデックス404の各値が交換されており、好ましくはソート・エンジン104によって、シンボル29のソート済みインデックス404が23から24にインクリメントされ、シンボル27のソート済みインデックス404が24から23にデクリメントされる。これらの変更は、図7で、変更された値を含む灰色の長方形と、変更されたソート済みインデックス404のポインタ値に対応する破線矢印で強調表示されている。
ここで図8を参照すると、ソート・エンジン104によって更新された図7の頻度テーブル401、ソート済みリスト403、及びテール・ポインタ407を表すブロック図が示されている。図8は、図7の頻度テーブル401及びソート済みリスト403の、ソート・エンジン104が受信したシンボル283を処理した後の状態を表している。具体的には、ソート・エンジン104は、頻度テーブル401のインデックス283にある頻度402を、図5のブロック502に従って0から1にインクリメントしている。さらに、ソート・エンジン104は、図5の判定ブロック504で、これがシンボル283の最初の出現であると決定している。その結果、図5のブロック506に従い、ソート・エンジン104は、シンボル283をソート済みリスト403の末尾(図8の例では、ソート済みリスト403のインデックス278)に挿入している。これによって、シンボル値283が、図7のテール・ポインタ407によって指し示されたエントリのシンボル値406のフィールド(例では、エントリ278)に挿入されている。さらに、これによって図7のテール・ポインタ値407(278)が、頻度テーブル401のエントリ283のソート済みインデックス404に格納されている。さらに、ソート・エンジン104は、テール・ポインタ407を278から279にインクリメントしている。これらの変更は、図8で、変更された値を含む灰色の長方形と、変更されたソート済みインデックス404のポインタ値及びテール・ポインタ407の値に対応する破線矢印で強調表示されている。
図3〜8で説明された方法で動作することによって、ソート・エンジン104は、頻度及び辞書式順序でソートされたシンボル403のリストを、LZ77エンジン102による入力ブロックのスキャンの終了時、又は終了に極めて近い時点で効果的に提供する。つまり、シンボルのソート時間(図10のタイミング図のブロック1003で図示される)は、最後のトークンに関連付けられたシンボルのソート済みリスト内での位置の更新に必要になる可能性のある時間を除き、LZ77エンジン102による入力ブロックのスキャン時間(図10のブロック1002で図示される)に重ね合わせられ、その結果、図9に示された従来の圧縮時間よりも合計圧縮時間が減少する。さらに、LZ77出力トークンのストリームの最後のトークン212に関連付けられたシンボルの、ソート済みリスト403内の位置の更新に必要な時間も、ほとんどの場合、極めて短くなる。これは、この時点では、頻度テーブル401内の頻度の分布が相対的に不均一である可能性が高く、最後のシンボルの頻度402のインクリメントが、ほとんどの場合、ソート済みリスト403の更新を必要とせず、更新が必要な場合でも、1つ上に移動するだけで済む可能性が高いからである。実際、最後のシンボルは、一般にブロック終結シンボルであり、それ以前に見られていないため、ソート済みリストの末尾に挿入されることになる。したがって、ソート・エンジン104は、必ずリテラルになり、バック・ポインタから指されることのないブロック終結シンボルについて、専用のチェックを行うことができ、ゆえに、ブロック終結シンボルのためにハフマン・コード・テーブルの構築を遅らせる必要はない。
ここで図9を参照すると、従来方法におけるDEFLATE方式入力ブロック圧縮に関連付けられた圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。圧縮の開始時に、ブロック902で、入力ブロックがスキャンされ、LZ77トークンのストリームが生成され、シンボルの出現頻度のヒストグラムが持続される。ブロック902が完了すると、ブロック903で、シンボルがその頻度による順序でソートされる。ブロック903が完了すると、ブロック904で、頻度でソートされたシンボルを使用してハフマン・コード・テーブルが構築される。ブロック904が完了すると、ブロック906で、ハフマン・コード・テーブルが使用されて、入力ブロックをハフマン・エンコードする、すなわち、LZ77トークン出力ストリームをハフマン・エンコードする。ブロック902、904、906、及び908に関連付けられた動作が連続して順番に実行され、その結果、合計圧縮時間は、図に示されるように、ブロック902、904、906、及び908のすべてに関連付けられた時間の合計になる。
ここで図10を参照すると、本明細書に記載された同時シンボル・リスト・ソートの実施形態によるDEFLATE方式入力ブロック圧縮に関連付けられた圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。圧縮の開始時に、ブロック1002で、本明細書に記載されているように、LZ77エンジン102が入力ブロック・メモリ101内の複数の文字から成る入力ブロックをスキャンし、トークン212のストリームを生成し、例えば、図3のブロック302〜308に関して説明されているように、各々の生成されるトークン212について繰り返される。圧縮開始に極めて近い時点、すなわち、最初のトークン212がLZ77エンジン102によって生成されたときに、ブロック1003で、ソート・エンジン104は、例えば図3のブロック312〜318に関して説明されているように、出現頻度及び等しい頻度内での辞書式のシンボル順序でソートされたシンボルのリストを継続的に維持する。ブロック1003での動作時間は、主としてブロック1002での動作時間の背後に有利に隠れることができる。これは、前述したように、LZ77エンジン102によって生成されたトークンに応答して図3のブロック316でシンボルのソート済みリストを維持するためにソート・エンジン104によって必要とされる時間が、ほとんどのトークンについて、図3のブロック302で次のトークンを生成するためにLZ77エンジン102によって必要とされる時間の背後に有利に隠れるからである。
LZ77エンジン102が複数の文字から成る入力ブロックのスキャンを完了し、ソート・エンジン104が(必要に応じて)最後のトークン212に関連付けられたシンボルについてソート済みリスト403の更新を完了した場合、ブロック1004で、ハフマン・コード・テーブル構築エンジン106は、ソート済みリスト403を使用してハフマン・コード・テーブルを構築する。それから、ブロック1006で、ハフマン・エンコーディング・エンジン108は、ブロック1004で構築されたハフマン・コード・テーブルを使用して、複数の文字から成る入力ブロックを、より正確には、LZ77エンジン102により生成された置換バック・ポインタと入力ブロックの置換されていないリテラルとをエンコードし、圧縮された出力を出力メモリ109に書き込む。(ハフマン・コード・テーブルもまたハフマン・エンコードされ、出力メモリに書き込まれる。これにより、解凍器が、圧縮に使用されたハフマン・コード・テーブルを再形成することができる)。図9と図10を比較することで観察できるように、LZ77エンジン102が入力ブロックをスキャンすると同時にソート・エンジン104がソート済みシンボル・リストを維持することによって、従来方法と比較して合計圧縮時間が有利に減少する。
ここで図11Aを参照すると、代替の実施形態によるソート済みリスト403を表すブロック図が示されている。図11Aの実施形態では、ソート済みリスト403の各エントリは、シンボル値406に関連付けられたハフマン・コード1108及びビット長1112をさらに含んでいる。この方法では、ハフマン・コード・テーブル構築エンジン106は、ソート済みリスト403のシンボルに対して、ハフマン・コード1108及び関連するビット長1112を割り当てることができる。好ましくは、ハフマン・コード・テーブル構築エンジン106は、標準的なハフマン・エンコーディングに従ってハフマン・コード1108を割り当てる。ビット長1112は、ハフマン・コード1108のビット数を示す。図11Aのソート済みリスト403の実施形態は、図4の頻度テーブル401と併せて、ハフマン・コード・テーブルとして使用されることが可能である。つまり、あるシンボル値(例えば、DEFLATE方式リテラル/長さテーブルの値0〜285、又はDEFLATE方式距離テーブルの値0〜29)を入力として与えられた場合、そのシンボル値は、頻度テーブル401へのインデックスとして使用されてシンボルのソート済みインデックス404の値を決定し、それから、このソート済みインデックス404の値は図11Aのソート済みリスト403のインデックスを指すように使用されて、シンボルに関連付けられたハフマン・コード1108が取得される。間接のレベルを回避してハフマン・コード・テーブルを実現する代替の実施形態が、図11Bに関して以下で説明される。
ここで図11Bを参照すると、代替の実施形態による頻度テーブル401を表すブロック図が示されている。図11Bの実施形態では、頻度テーブル401の各エントリは、シンボルに関連付けられたハフマン・コード・フィールド1108及びビット長1112をさらに含み、上記シンボルの値は、頻度テーブル401へのインデックスである。この方法で、ハフマン・コード・テーブル構築エンジン106は、シンボルの値が頻度テーブル401のインデックスを指すシンボルに対してハフマン・コード1108と関連するビット長1112とを割り当て、(例えば、図10のブロック1004で)頻度テーブル401の一部として直接ルックアップ・ハフマン・コード・テーブルを構築することができる。
ここで図12を参照すると、代替の実施形態による図1のハードウェア・データ圧縮器100に関連付けられたハードウェアを表すブロック図が示されている。図12のハードウェア・データ圧縮器100は、ソート済みリスト変更フラグ1202及びソート済みリスト未変更カウンタ1204を含む。ソート・エンジン104がソート済みリスト403を(例えば、ブロック514及び522で)変更するたびに、ソート・エンジン104は、ソート済みリスト変更フラグ1202を設定し、ソート済みリスト未変更カウンタ1204をリセットする。ハフマン・コード・テーブル構築エンジン106は、(例えば、ブロック1004で)ソート済みリスト403を使用してハフマン・コード・テーブルの構築を成功裏に完了するたびに、ソート済みリスト変更フラグ1202をクリアする。ハフマン・コード・テーブル構築エンジン106がハフマン・コード・テーブルの構築の処理中である場合、ソート・エンジン104がソート済みリスト403を変更すると、ハフマン・コード・テーブル構築エンジン106は、ハフマン・コード・テーブルの構築を停止し、それらの構築を再開する。ソート・エンジン104は、LZ77エンジン102がソート済みリスト403の変更を必要としないトークン212を生成するたびに、ソート済みリスト未変更カウンタ1204をインクリメントする。ソート済みリスト変更フラグ1202及びソート済みリスト未変更カウンタ1204の使用方法については、図13に関する一実施形態で説明される。
ここで図13を参照すると、代替の実施形態での圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。図13の実施形態は図10の実施形態に類似しているが、図13の実施形態では、ブロック1004がブロック1304で置き換えられている。ブロック1002でLZ77圧縮エンジン102が入力ブロックをスキャンすると同時に、且つブロック1003でソート・エンジン104がソート済みリスト403を維持すると同時に、ブロック1304で、ハフマン・コード・テーブル構築エンジンが動作して、ハフマン・コード1108をソート済みリスト403のシンボル値406に割り当てる。その結果、ブロック1304でソート済みリスト403を使用してハフマン・コード・テーブルを構築するために必要な時間が、ブロック1002での入力ブロックのスキャン時間及びブロック1003でのソート済みリストの維持時間に大きく重ね合わせられ、隠され、これにより、合計圧縮時間がさらに減少する。好ましくは、図13の実施形態は、図12のソート済みリスト変更フラグ1202、及び、必要に応じてソート済みリスト未変更カウンタ1204を採用する。つまり、ソート・エンジン104は、(例えば、ブロック514又は522で)ソート済みリスト403を変更するたびに、ソート済みリスト変更フラグ1202を設定し、ハフマン・コード・テーブル構築エンジン106に通知し、応答的に、ハフマン・コード・テーブル構築エンジン106は、ソート済みリスト403内のシンボル値406を使用してハフマン・コード値1108の構築を開始する。ソート・エンジン104がソート済みリスト403を再び変更する前に、ハフマン・コード・テーブル構築エンジン106がハフマン・コード・テーブルの構築を成功裏に完了した場合、ハフマン・コード・テーブル構築エンジン106は、ソート済みリスト変更フラグ1202をクリアする。ブロック1002で入力ブロックのスキャンが完了しているとき、ソート済みリスト変更フラグ1202がクリアされていると、ハフマン・エンコーディング・エンジン108は、ブロック1006で入力ブロックのハフマン・エンコーディングを開始する。この方法で、ブロック1304でハフマン・コード・テーブルを構築するために必要な時間の一部、又は、場合によってはすべてが、ブロック1002での入力ブロックのスキャン時間及びブロック1003でのソート済みリストの維持時間と重ね合わせられ、隠される。
一実施形態では、ハフマン・コード・テーブル構築エンジン106は、ソート・エンジン104がソート済みリスト403を変更するたびに、ハフマン・コード値1108を構築する。しかし、代替の実施形態では、ソート・エンジン104がソート済みリスト403を変更したとき、ハフマン・コード・テーブル構築エンジン106は、ソート済みリスト未変更カウンタ1204が、ソート・エンジン104がソート済みリスト403を最後に変更して以降、所定数のトークン212が見られたことを示す場合にのみ、ハフマン・コード値1108の構築を開始する。上記所定数は、プログラム可能にすることができる。この方法では、ブロック1002における入力ブロックのスキャンの間、ハフマン・コード・テーブル構築エンジン106が、ブロック1304における動作をより低い頻度で実行することになるため、ハードウェア・データ圧縮器100の消費電力が削減され、テーブル・メモリ107へのアクセス輻輳を減らすことが可能である。ソート済みリスト未変更カウンタ1204を採用してハフマン・コード・テーブルの構築を抑制する実施形態について説明されているが、別の基準を使用する他の実施形態が企図される。例えば、ソート・エンジン104がソート済みリスト403を変更したとき、ハフマン・コード・テーブル構築エンジン106は、ソート・エンジン104が最後にソート済みリスト403を変更して以降、所定数のトークン212ではなく、所定数のシンボルが見られた場合にのみ、ハフマン・コード値1108の構築を開始する。別の例では、ソート・エンジン104がソート済みリスト403を変更したとき、ハフマン・コード・テーブル構築エンジン106は、ソート・エンジン104が最後にソート済みリスト403を変更して以降、所定数のトークン212ではなく、所定数のクロック・サイクルが経過した場合にのみ、ハフマン・コード値1108の構築を開始する。
ただし、入力ブロックのスキャンの初期では、頻度の分布が相対的に均一になる可能性が高いため、通常、ソート済みリスト403は頻繁に変更されることが注目される。しかし、入力ブロックのスキャンの後期では、前述したように、頻度の分布が相対的に不均一になる可能性が高いため、通常、ソート済みリスト403が変更される頻度は低くなる。したがって、場合によっては、ハフマン・コード・テーブル構築エンジン106によるハフマン・コード値1108の最後の構築は、入力ブロックのスキャンが完了されるかなり前に始まることになり、場合によっては、ハフマン・コード値1108の最後の構築は、入力ブロックのスキャンが完了される前に完了することになる。例えば、最後のN個のトークン212がソート済みリスト403における変更を引き起こさず、入力ブロックをスキャンして最後のN個のトークン212を生成するためにLZ77エンジン102によって費やされる時間が、少なくとも、ソート済みリスト403からハフマン・コード・テーブルを構築するためにハフマン・コード・テーブル構築エンジンによって必要とされる時間と同じくらい大きい場合である。
可逆圧縮アルゴリズム(例えば、LZ77)を採用する圧縮エンジンによってトークン・ストリームが生成されるのと同時に、ソート・エンジンがトークン・ストリーム内の出現頻度でソートされたシンボルのリストを維持するハードウェア・データ圧縮器の実施形態が説明されたが、不可逆圧縮アルゴリズム(JPEG、MPEG、MP3)を採用する圧縮エンジンによってトークン・ストリームが生成されるのと同時に、ソート・エンジンがトークン・ストリーム内の出現頻度でソートされたシンボルのリストを維持し、その後、その出力が、ソート済みシンボル・リストからの恩恵を受けるエンコーディング・エンジン(例えば、ハフマン・エンコーディング)によって、コード・テーブルを構築するためにエンコードされる他の実施形態が企図されるということが理解されるべきである。
従来方法での(すなわち、本明細書に記載されているような、入力ブロックのスキャンと同時のインクリメンタルな方法ではない)シンボルのリストのソートは、通常、メモリを大量に使用するということに注目するべきである。このことは、システム・メモリなどの大量のメモリへのアクセスを一般に有するソフトウェア・データ圧縮プログラム(例えば、gzip)にとっては、問題にならない可能性がある。しかし、大量のメモリの使用は、相対的に少量のメモリを使用することが望ましいハードウェア・データ圧縮器にとって、ハードウェア・データ圧縮器上のメモリが大きくなるほどメモリへのアクセス待ち時間が大きくなるため、コストと性能の両方の理由から望ましくない。したがって、ソート済みリストを、入力ブロックのスキャンと同時にインクリメンタルに維持することは、ハードウェア・データ圧縮器の実施形態にとって特に有利である。
「ダイナミック−プライム」ハフマン・コーディング
ここで図14Aを参照すると、ダイナミック−プライム・ハフマン・エンコーディングと連動してデータ圧縮を実行するための図1のLZ77エンジン102の動作を表すフローチャートが示されている。好ましくは、図14AでのLZ77エンジン102の動作は、図14Bによるハフマン・コード・テーブル構築エンジン106の動作と連動し、且つ図14Cによるハフマン・エンコーディング・エンジン108の動作と連動して実行され、したがって、例えば図16に示されるように、3つの動作の大部分が同時に実行されて、複数の文字から成る入力ブロックのハードウェア・データ圧縮を実現する。フローは、ブロック1402から始まる。
ブロック1402で、LZ77エンジン102は、入力ブロック内の現在の検索ターゲット位置を初期化する。好ましくは、ハードウェア・データ圧縮器100は、検索ターゲット位置の値を格納するレジスタ(図に示されていない)を含む。現在の検索ターゲット位置は、複数の文字から成る入力ブロックへのインデックスである。好ましくは、検索ターゲット位置は、入力ブロックの2番目の文字を指し示すように初期化される。フローはブロック1404に進む。
ブロック1404で、LZ77エンジン102は、入力ブロック内の検索ターゲット位置で始まる文字列の一致を検索する。つまり、LZ77エンジン102は、入力ブロック内の検索ターゲット位置で始まる文字の文字列、ターゲット文字列を取り込み、ターゲット文字列との一致について入力ブロックの以前の部分を検索する。一般的に言えば、LZ77エンジン102は、入力ブロック内の以前の部分で検出可能な最長の文字列の一致を検索する。ただし、LZ77エンジン102は、検索時間を削減し、及び/又はバック・ポインタの最大長を制限するために、検索される文字列の長さを制限することができる。さらに、LZ77エンジン102は、検索時間を削減し、及び/又はバック・ポインタの最大距離を制限するために、現在の検索ターゲット位置から後方に検索する距離を制限することができる。LZ77エンジン102は、現在の検索ターゲット位置の文字列との一致について、入力ブロック内の以前の部分を検索するために、さまざまな手法を採用することができ、それらの一部は、図24及び25に関して下で説明されている2つのハッシュ・テーブルの実施形態などについて、本明細書に記載されている。フローはブロック1406に進む。
ブロック1406で、LZ77エンジン102はトークン212を生成する。前述したように、トークン212は、バック・ポインタ又は入力ブロックからのリテラルのいずれかである。一実施形態では、入力ブロックからリテラルを生成することは、単にリテラルを入力ブロック・メモリ101内の適所に(in place)残すことであるため、上記リテラルは、その後、ハフマン・エンコーディング・エンジン108によって入力ブロック・メモリ101から読み出され、ダイナミック−プライム・ハフマン・コード・テーブルを使用してハフマン・エンコードされることが可能である。一実施形態では、前述したように、バック・ポインタは、バック・ポインタ・メモリ105に書き込まれ、メモリ105内のフラグが、置換バック・ポインタの存在を示すように、置換される/一致したターゲット文字列の先頭の文字の入力ブロックでの位置に対応して設定される。LZ77エンジン102は、検索ターゲット位置をさらに更新する。好ましくは、LZ77エンジン102は、バック・ポインタを生成する場合、一致する文字列の長さずつ検索ターゲット位置をインクリメントし、一方、リテラルを生成する場合、生成されるリテラルの数ずつ検索ターゲット位置をインクリメントする。ソート・エンジン104を含む実施形態では、図3のブロック316でのように、ソート済みリスト403がさらに更新される。フローは、判定ブロック1408に進む。
判定ブロック1408で、LZ77エンジン102は、ダイナミック−プライム・ハフマン・コード・テーブルの構築を信号で伝えることができるように、複数の文字から成る入力ブロックの初期部分をスキャンしたかどうかを決定する。入力ブロックの初期部分は、さまざまな方法で決定されることが可能である。一実施形態では、LZ77エンジン102は、所定数の入力文字(例えば、3,000文字)をスキャンした後に、初期部分をスキャンしたと決定する。一実施形態では、LZ77エンジン102は、入力ブロック・サイズのうちの所定部分(例えば、入力ブロックの複数の文字のうちの最初の10分の1)をスキャンした後に、初期部分をスキャンしたと決定する。一実施形態では、LZ77エンジン102は、それまでの入力ブロック内で少なくとも第1の所定回数(例えば、1回、2回、3回)観測されたシンボル空間のシンボルの総数が、第2の所定値よりも大きい場合に、初期部分をスキャンしたと決定する。例えば、第1の所定回数を3と仮定すると、ハードウェア・データ圧縮器100は、頻度402を3の値にインクリメントするたびに、ゼロに初期化されていたカウンタをインクリメントし、カウンタが第2の所定値(例えば、85)に達したときに、初期部分のスキャンが完了する。第2の所定値は、シンボル空間内のシンボル数の所定パーセンテージ(例えば、33%)にすることが可能である。一実施形態では、入力ブロックの初期部分は、図18及び19などに関して説明されているように、ソート済みリスト403に対する変更の発生に基づいて、好ましくはソート・エンジン104によって決定される。一実施形態では、初期部分は、例えば、ハードウェア・データ圧縮器への圧縮命令のオペランドとして、ユーザ指定されることが可能である。一般的に言えば、圧縮速度を犠牲にして圧縮効率を向上するには、より大きい初期部分の値が選択され、圧縮効率を犠牲にして圧縮速度を向上するには、より小さい初期部分の値が選択されることに注目するべきである。LZ77エンジン102が入力ブロックの初期部分のスキャンを完了した場合、フローはブロック1412に進み、そうでない場合、フローはブロック1414に進む。
ブロック1412で、LZ77エンジン102は、ハフマン・コード・テーブルを構築するようにハフマン・コード・テーブル構築エンジン106に信号で伝える。つまり、入力ブロックの初期部分のスキャンが完了しており、したがって、ハフマン・コード・テーブルが(例えば、図14Bのブロック1424で)構築されることが可能であり、ハフマン・エンコーディングが(例えば、図14Cのブロック1434で)開始可能である。フローはブロック1404に戻って、検索ターゲット位置の更新された値で一致を検索する。図14Aは、いったん初期部分がスキャンされているとブロック1404、1406、及び1408のループを通るたびにハフマン・コード・テーブルを構築するように信号で伝えることを示すように見えるが、この信号送信が実行されるのは1回だけであることが理解されるべきである。
ブロック1414で、頻度402は、ブロック1406で生成されたトークン212に関連付けられたシンボルの各々について更新される。一実施形態では、ソート・エンジン104が、各シンボルの頻度402をインクリメントする。別の実施形態では、ソート・エンジン104が存在せず、LZ77エンジン102が各シンボルの頻度402をインクリメントする。さらに別の実施形態では、ソート・エンジン104が存在せず、図2Aに関して説明されている、ソート・エンジン104に提供するためにLZ77エンジン102がトークン212を生成するのと同様の方法で、LZ77エンジン102がハフマン・コード・テーブル構築エンジン106に提供するためにトークン212を生成し、ハフマン・コード・テーブル構築エンジン106が各シンボルの頻度402をインクリメントする。フローはブロック1404に戻って、検索ターゲット位置の更新された値で一致を検索する。ブロックの終わりに達すると(例えば、ブロック終結文字に直面すると)、フローは終了し、ブロック1412、1414、又は1416からブロック1404に戻らず、図14Aに従う動作が次の入力ブロックに対して繰り返されることが理解されるべきである。
前述したように、入力ブロックの初期部分のスキャンが完了すると、頻度テーブル401内の頻度402は更新されなくなる。有利なことに、ハードウェア・データ圧縮器102は、入力ブロックの初期部分のスキャンが完了すると、頻度テーブル401の更新を停止し、その間、入力ブロックをスキャンする。これは、頻度402を更新するためのテーブル・メモリ107へのアクセス数が減少することによって、消費電力量が低減し、テーブル・メモリ107の競合が減少し、その他のエンジンがテーブル・メモリ107により素早くアクセスできるようになることにより、特にテーブル・メモリ107のポートが共有される実施形態において性能を改善することができるため、有利である。さらに、より少ないポートでのメモリの使用を容易にすることができるため、デザインを小さくすることができる。
ここで図14Bを参照すると、ダイナミック−プライム・ハフマン・エンコーディングと連動してデータ圧縮を実行するための図1のハフマン・コード・テーブル構築エンジン106の動作を表すフローチャートが示されている。フローは、ブロック1422から始まる。
ブロック1422で、ハフマン・コード・テーブル構築エンジン106は、ハフマン・コード・テーブルを構築するための信号を受信する。一実施形態では、LZ77エンジン102が、ハフマン・コード・テーブルを構築するようにハフマン・コード・テーブル構築エンジン106に信号で伝える。一実施形態では、ソート・エンジン104が、ハフマン・コード・テーブルを構築するようにハフマン・コード・テーブル構築エンジン106に信号で伝える。フローはブロック1424に進む。
ブロック1424で、ハフマン・コード・テーブル構築エンジン106は、入力ブロックの初期部分のみのスキャン後の、すなわち、ブロック1422でハフマン・コード・テーブル構築エンジン106に信号が送信された時点での頻度402の値を有する頻度テーブル401を使用して、ダイナミック−プライム・ハフマン・コード・テーブルを構築する。図17A〜17Cは、ダイナミック−プライム・ハフマン・コード・テーブルが構築される実施形態を表している。フローはブロック1426に進む。
ブロック1426で、ハフマン・コード・テーブル構築エンジン106は、ハフマン・エンコーディング・エンジン108に、入力ブロックのハフマン・エンコーディングを開始するように信号で伝える。フローはブロック1426で終了する。
ここで図14Cを参照すると、ダイナミック−プライム・ハフマン・エンコーディングと連動してデータ圧縮を実行するための図1のハフマン・エンコーディング・エンジン108の動作を表すフローチャートが示されている。フローは、ブロック1432から始まる。
ブロック1432で、ハフマン・エンコーディング・エンジン108は、入力ブロックのハフマン・エンコーディングを開始するために図14Bのブロック1426で発生された信号を受信する。フローはブロック1434に進む。
ブロック1434で、ハフマン・エンコーディング・エンジン108は、ブロック1424で構築されたハフマン・コード・テーブルを使用して入力ブロック全体をエンコードする。つまり、ハフマン・エンコーディング・エンジン108は、入力ブロックの初期部分のみのスキャンに基づいてブロック1424で構築されたハフマン・コード・テーブルを使用して、入力ブロック全体のバック・ポインタ及び置換されていないリテラルをハフマン・エンコードし、ハフマン・エンコードされた出力(及び、ハフマン・エンコードされたバージョンのハフマン・コード・テーブル)を出力メモリ109に格納する。フローはブロック1434で終了する。
ここで図15を参照すると、従来方法におけるDEFLATE方式入力ブロック圧縮に関連付けられた圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。圧縮時間の開始時に、ブロック1502で、入力ブロック全体がスキャンされ、LZ77トークンのストリームが生成され、シンボルの出現頻度のヒストグラムが持続される。ブロック1502が完了すると、ブロック1504で、入力ブロック全体に対して持続されたシンボルの頻度を使用して、ハフマン・コード・テーブルが構築される。ブロック1504が完了すると、ブロック1506でハフマン・コード・テーブルが使用されて、入力ブロックをハフマン・エンコードする、すなわち、LZ77トークン出力ストリームをハフマン・エンコードする。ブロック1502、1504、及び1506に関連付けられた動作が連続して順番に実行され、その結果、合計圧縮時間は、図に示されるように、ブロック1502、1504、及び1506のすべてに関連付けられた時間の合計になる。
ここで図16を参照すると、本明細書に記載されたダイナミック−プライム・ハフマン・コード・テーブルの実施形態によるDEFLATE方式入力ブロック圧縮に関連付けられた圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。圧縮時間の開始時に、ブロック1602−Aで、本明細書に記載されているように、LZ77エンジン102が入力ブロック・メモリ101内の複数の文字から成る入力ブロックの初期部分をスキャンし、トークン212のストリームを生成し、例えば、図14A(及び図3のブロック302〜308)に関して説明されているように、各々の生成されるトークン212について繰り返される。入力ブロックの初期部分のスキャンが完了した後に、ハフマン・コード・テーブルを構築するように信号が(例えば、図14Aのブロック1412に従って)与えられ、ブロック1604で、ハフマン・コード・テーブル構築エンジン106が、(例えば、図14Bのブロック1424に従って)ブロック1602−Aでの入力ブロックの初期部分のスキャンの間に維持された頻度テーブル401の頻度402を使用して、ハフマン・コード・テーブルを構築する。さらに、ブロック1602−Bで、LZ77エンジン102は、入力ブロック・メモリ101内の複数の文字から成る入力ブロックの残りの部分を引き続きスキャンし、トークン212のストリームを生成する。
ハフマン・コード・テーブル構築エンジン106が、ブロック1604で初期部分の頻度を使用してダイナミック−プライム・ハフマン・コード・テーブルの構築を完了すると、ブロック1606で、ハフマン・エンコーディング・エンジン108が、ダイナミック−プライム・ハフマン・コード・テーブルを使用して、入力ブロック全体(又は、より正確には、LZ77エンジン102によって生成された置換バック・ポインタ及び入力ブロックの置換されていないリテラル)をハフマン・エンコードし、圧縮された出力を出力メモリ109に書き込む。従来方法で実行されていたような入力ブロック全体のスキャンからではなく、入力ブロックの初期部分のみのスキャンからの出現頻度を使用してダイナミック−プライム・ハフマン・コード・テーブルが構築されるため、ブロック1604及び1606での動作時間は、主としてブロック1602−Bでの動作時間の背後に有利に隠れることが可能である。図15及び図16を比較することによって観察できるように、ダイナミック−プライム・ハフマン・コード・テーブル、つまり、入力ブロックの初期部分のみのスキャンからの出現頻度を使用して構築されたハフマン・コード・テーブルを使用することで、合計圧縮時間が従来方法と比較して有利に削減される。
ここで図17Aを参照すると、一実施形態によるダイナミック−プライム・ハフマン・コード・テーブルを構築するためのハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック1702から始まる。
ブロック1702で、頻度テーブル401の頻度402は、例えばLZ77エンジン102、ソート・エンジン104、又はハフマン・コード・テーブル構築エンジン106によって、ゼロに初期化される。フローはブロック1704に進む。
ブロック1704で、LZ77エンジン102は入力ブロックの初期部分をスキャンし、生成されたトークンに関連付けられたシンボルの頻度402が(例えば、LZ77エンジン102、ソート・エンジン104、又はハフマン・コード・テーブル構築エンジン106によって)インクリメントされる。フローはブロック1706に進む。
ブロック1706で、ハフマン・コード・テーブルの構築の初期部分で(例えば、ブロック1604で)ゼロの値の頻度402を有するシンボル空間内(例えば、リテラル及び長さテーブル401のシンボル値0〜285と、距離のテーブル401のシンボル値0〜29)の各シンボルについて、ハフマン・コード・テーブル構築エンジン106(又は、代替の実施形態におけるソート・エンジン104)は、ゼロの値の頻度をゼロ以外の値で置換する。好ましくは、ゼロ以外の値は、小さい値、例えば、値1である。これは、ハフマン・コード・テーブルが構築されるときに、シンボル空間内の各シンボル値についてハフマン・コードが存在するようにするためである。これが必要なのは、前述したように、(例えば、ブロック1602−Aで)入力ブロックの初期部分のスキャンに現れなかったシンボルが、(例えば、ブロック1602−Bで)入力のブロックの残りの部分のスキャンに現れる可能性があり、ハフマン・エンコーディング・エンジン108が、(例えば、ブロック1606で)入力ブロックをハフマン・エンコードするときに、ダイナミック−プライム・ハフマン・コード・テーブル内にそのシンボルのハフマン・コード値を必要とするからである。フローはブロック1708に進む。
ブロック1708で、ハフマン・コード・テーブル構築エンジン106は、ブロック1702〜1706に従って作成された頻度テーブル401の頻度402を使用して、ハフマン・コード・テーブルを構築する。重要なことに、構築されたダイナミック−プライム・ハフマン・コード・テーブルは、各シンボルがゼロ以外の頻度402の値を持っているため、シンボル空間内の各シンボルについてハフマン・コード値を含むことになる。前述したように、好ましくは、ハフマン・コード・テーブル構築エンジン106は、標準的なハフマン・コード・テーブルを構築する。フローはブロック1708で終了する。
ここで図17Bを参照すると、一実施形態によるダイナミック−プライム・ハフマン・コード・テーブルを構築するためのハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック1712から始まる。
ブロック1712で、頻度テーブル401の頻度402は、1に、又はその他のゼロ以外の値に初期化される。各頻度402をゼロ以外の値に初期化した結果、ハフマン・コード・テーブル構築エンジン106は、ハフマン・コードを(例えば、ブロック1718で構築される)ダイナミック−プライム・ハフマン・コード・テーブルのシンボル空間の各シンボルに割り当てることになる。フローはブロック1714に進む。
ブロック1714で、LZ77エンジン102は、入力ブロックの初期部分をスキャンし、生成されたトークンに関連付けられたシンボルの頻度402は、上のブロック1704で説明されたのと同様の方法でインクリメントされる。フローはブロック1718に進む。
ブロック1718で、ハフマン・コード・テーブル構築エンジン106は、ブロック1712〜1714に従って作成された頻度テーブル401の頻度402を使用して、ハフマン・コード・テーブルを構築する。重要なことに、構築されたダイナミック−プライム・ハフマン・コード・テーブルは、ブロック1712で初期されることによって保証されているように、各シンボルがゼロ以外の頻度402の値を有するため、シンボル空間内の各シンボルについてハフマン・コード値を含むことになる。フローはブロック1718で終了する。
ここで図17Cを参照すると、一実施形態によるダイナミック−プライム・ハフマン・コード・テーブルを構築するためのハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック1722から始まる。
ブロック1722で、頻度テーブル401の頻度402は、シンボル空間のシンボルに対応する事前に蓄積された(pre-compiled)ゼロ以外の値のセット内で指定されたゼロ以外の値のセットに初期化される。つまり、各シンボルの頻度402を、図17Bのブロック1712で実行されたように同じゼロ以外の値に割り当てるのではなく、ブロック1722で、各シンボルの頻度は、シンボル空間のシンボルの相対的頻度の見込みに関する事前知識(すなわち、入力ブロックの圧縮開始の前の知識)に基づいて特定のシンボルに対する調整された値に初期化される。例えば、長さのより短いバック・ポインタが極めて頻繁に出現する傾向があることが一般に知られている。したがって、事前に蓄積されたゼロ以外の頻度のセットは、シンボル空間のより短いバック・ポインタ長について、比較的大きいゼロ以外の頻度値を含んでいる可能性がある。別の例では、入力ブロックがASCII文字テキストであると仮定する。入力ブロック内のASCIIの「E」の頻度が、ASCIIの「Z」の頻度よりも高くなる見込みが高いことが一般に知られている。したがって、事前に蓄積されたゼロ以外の頻度のセットは、ASCIIの「Z」についてよりもASCIIの「E」について、より大きいゼロ以外の頻度値を含むことになる。このようにして、初期のゼロ以外の値は、同じゼロ以外の値を使用してあらゆるシンボルを初期化するのではなく、教授された推測に基づいて頻度402を事前に偏らせる。前述したように、この方法の利点は、図2A〜8などでのようにソート・エンジン104が使用される実施形態において、頻度テーブル401の頻度402の初期値の不均一性によって、必要なソート量、すなわち、図5のブロック514及び522でのような、ソート済みリスト403のシンボル位置交換の量を減らすことができることである。一実施形態では、ハードウェア・データ圧縮器100は、事前に蓄積されたゼロ以外の値の複数のセットを使用することができ、入力ブロックの取得元のファイルのタイプ(例えば、画像ファイル、オーディオ・ファイル、テキスト・ファイル、スプレッドシート、ワード・プロセッサやプレゼンテーション・アプリケーションによって生成されたファイル、又は他のタイプのファイル)などの基準に基づいて、事前に蓄積されたセットのうちの1つを選択する。フローはブロック1724に進む。
ブロック1724で、LZ77エンジン102は、入力ブロックの初期部分をスキャンし、生成されたトークンに関連付けられたシンボルの頻度402は、上のブロック1704で説明されたのと同様の方法でインクリメントされる。フローはブロック1728に進む。
ブロック1728で、ハフマン・コード・テーブル構築エンジン106は、ブロック1722〜1724に従って作成された頻度テーブル401の頻度402を使用して、ハフマン・コード・テーブルを構築する。重要なことに、構築されたダイナミック−プライム・ハフマン・コード・テーブルは、ブロック1722で初期されることによって保証されているように、各シンボルがゼロ以外の頻度402の値を有するため、シンボル空間内の各シンボルについてハフマン・コード値を含むことになる。フローはブロック1728で終了する。
ここで図18を参照すると、一実施形態による図1のハードウェア・データ圧縮器100に関連付けられたハードウェアを表すブロック図が示されている。図12のハードウェア・データ圧縮器100は、ソート済みリスト変更カウンタ(sorted list change counter:SLCC)1804、しきい値1806、シンボル・カウントダウン・カウンタ(symbol countdown counter:SCDC)1808、及びこれらが接続されるロジック1802を含む。しきい値1806は、プログラム可能なレジスタにすることができる。SLCC1804は、SLCC1804の最後のリセット以降、ソート済みリスト403が(例えば、ブロック514又はブロック522で)変更された回数のカウントを示す。SCDC1808は、所定値をロードされ、シンボルの頻度402が(例えば、ブロック1414で)インクリメントされるたびにカウントダウンされる。図19に関してより詳細に説明されているように、SCDC1808がゼロにカウントダウンされたとき、SLCC1804がしきい値1806よりも小さい場合、ロジック1802は、ハフマン・コード・テーブルを構築するように信号で伝え、そうでない場合、SCDC1808が再び所定値をロードされる。好ましくは、図18のハードウェアが、(例えば、図14Aのブロック1412での)LZ77エンジン102ではなくソート・エンジン104に含まれ、ソート・エンジン104が、(例えば、図19のブロック1914で)ハフマン・コード・テーブルを構築するようにハフマン・コード・テーブル構築エンジン106に信号で伝える。一実施形態では、カウンタ1808は、シンボル頻度402がインクリメントされるたびではなく、トークン212が生成されるたびにカウントダウンされる。一実施形態では、カウンタ1808は、シンボル頻度402がインクリメントされるたびではなく、クロック・サイクルごとにカウントダウンされる。
ここで図19を参照すると、ハフマン・コード・テーブルの構築を信号で伝えるためのソート・エンジン104の動作を表すフローチャートが示されている。フローは、ブロック1902から始まる。
ブロック1902で、ソート・エンジン104は図18のSLCC1804をゼロに初期化する。フローはブロック1904に進む。
ブロック1904で、ソート・エンジン104は初期カウント又は所定値(例えば、100)をSCDC1808にロードする。フローはブロック1906に進む。
ブロック1906で、ソート・エンジン104は、LZ77エンジン102からトークン212を受信し、そのトークン212に関連付けられた各シンボルに応答してSCDC1808をデクリメントする。また、トークン212に関連付けられたシンボルに基づいてソート済みリスト403の変更が必要だった場合、ソート・エンジン104はSLCC1804をインクリメントする。フローは、判定ブロック1908に進む。
判定ブロック1908で、ロジック1802は、SCDC1808の値がゼロに達したかどうかを決定する。ゼロに達した場合、フローは判定ブロック1912に進み、そうでない場合、フローはブロック1906に戻って次のトークン212を待機する。
判定ブロック1912で、ロジック1802は、SLCC1804がしきい値1806よりも小さいかどうかを決定する。小さい場合、フローは判定ブロック1914に進み、そうでない場合、フローはブロック1904に戻る。
ブロック1914で、ロジック1802は、ハフマン・コード・テーブルを構築するようにハフマン・コード・テーブル構築エンジン106に信号で伝える。一実施形態では、ソート・エンジン104は、入力ブロックの少なくとも最小文字数(例えば、500又は5%)がスキャンされるまで、ハフマン・コード・テーブルを構築するように信号で伝えない。フローはブロック1914で終了する。
ここで図20を参照すると、代替の実施形態によるDEFLATE方式入力ブロック圧縮に関連付けられた圧縮時間の構成要素をグラフィカルに表すタイミング図が示されている。上の図14A〜19の説明から観察できるように、入力ブロックの初期部分のみがスキャンされた後に入力ブロックのハフマン・エンコードを開始することによって、合計圧縮時間が有利に削減されることが可能である。図20の代替の実施形態では、ハードウェア・データ圧縮器100は、入力ブロックの初期部分のスキャンから維持された頻度を使用して構築されたダイナミック−プライム・ハフマン・コード・テーブルを使用するのではなく、複数の事前蓄積済みハフマン・コード・テーブルのうちの1つを選択して、入力ブロックの初期スキャンのみが実行された後に入力ブロックのハフマン・エンコーディングを開始し、それによって、ハフマン・エンコーディング時間を入力ブロックの残りの部分のスキャン時間に重ね合わせることによる恩恵を享受する。この実施形態では、ハードウェア・データ圧縮器100は、入力ブロックの初期部分のスキャンの間、事前蓄積済みハフマン・コード・テーブルの各々について、事前蓄積済みハフマン・コード・テーブルを使用して作り出された圧縮済み出力のサイズを記録する。それから、ハードウェア・データ圧縮器100は、初期部分を最も小さい出力に圧縮した事前蓄積済みハフマン・コード・テーブルを選択し、選択された事前蓄積済みハフマン・コード・テーブルを使用して入力ブロック全体をハフマン・エンコードする。
圧縮の開始時に、ブロック2002−AでLZ77エンジン102は、本明細書で説明されているように、入力ブロック・メモリ101内の複数の文字から成る入力ブロックの初期部分をスキャンし、トークン212のストリームを生成する。入力ブロックの初期部分がスキャンされると、ブロック2003で、ハードウェア・データ圧縮器100は、複数の事前蓄積済みハフマン・コード・テーブルの対(例えば、リテラル/長さテーブル及び距離テーブル)の各々を使用して、事前蓄積済みハフマン・コード・テーブルの対を使用して入力ブロックの初期部分をハフマン・エンコードするのに作り出されるであろう出力のサイズを計算する(ただし、作り出さない)。さらに、ブロック2002−Bで、LZ77エンジン102は、入力ブロック・メモリ101内の複数の文字から成る入力ブロックの残りの部分を引き続きスキャンし、トークン212のストリームを生成する。
入力ブロックの初期部分がスキャンされた後に、ブロック2004で、ハードウェア・データ圧縮器100は、事前蓄積済みハフマン・コード・テーブルの対のうちの1つを選択する。それから、ブロック2006で、ハフマン・エンコーディング・エンジン108は、選択された事前蓄積済みハフマン・コード・テーブルの対を使用して入力ブロック全体をハフマン・エンコードし、圧縮された出力を出力メモリ109に書き込む。ブロック2004及び2006での動作時間は、図に示されるように、ブロック2002−Bでの動作時間の背後に有利に隠れて、合計圧縮時間を有利に削減することができる。
図20の実施形態は、ハフマン・コード・テーブル構築エンジン106の負担を軽減するという、図14A〜19の実施形態を上回る利点を持つ可能性がある。ただし、図14A〜19のダイナミック−プライム・ハフマン・コード・テーブルの実施形態は、図20の実施形態と同じ高速な圧縮速度の恩恵を享受する可能性が高いが、さらなる利点を有している。図14A〜19の実施形態は、ハードウェア・データ圧縮器100が選択するための適切な事前蓄積済みハフマン・コード・テーブルが存在しない入力ブロックに対して、図20の実施形態よりも小さい出力を生成する可能性が高い。例えば、入力ブロックの文字が、事前蓄積済みハフマン・コード・テーブルが存在しない比較的難解な言語の文字、例えば、ハンガリー語のユニコードであると仮定する。その場合、図14A〜19の実施形態に従って構築されたダイナミック−プライム・ハフマン・コード・テーブルは、事前蓄積済みハフマン・コード・テーブルの対よりも小さい出力を生成する可能性が高い。
一致した文字列又は一致した文字列へのバック・ポインタを選択的にハフマン・エンコードする事前ハフマン・エンコーディング
ここで図21を参照すると、図1のハードウェア・データ圧縮器100の一部を表すブロック図が示されている。図1のLZ77エンジン102は、図1のテーブル・メモリ107と通信する。テーブル・メモリ107は、「参照」ハフマン・コード・テーブル2102を保持する。図22及び23に関してより詳細に説明されているように、参照ハフマン・コード・テーブル2102は、LZ77エンジン102によって、トークンを「事前ハフマン・エンコード(pre-Huffman encode)」してトークンのサイズを決定するために使用され、それによって、一致した文字列のリテラルを生成するのか、それとも一致した文字列へのバック・ポインタを生成するのかを判定する。参照ハフマン・コード・テーブル2102は、後でLZ77エンジン102の出力ストリームをハフマン・エンコードするためにハフマン・エンコーディング・エンジン108によって使用される同じハフマン・コード・テーブルである場合もあれば、そうでない場合もある。
LZ77エンジン102は、参照ハフマン・コード・テーブル2102を使用して2つのサイズを決定するロジックを含む。サイズXと呼ばれる第1のサイズは、一致した文字列のリテラル・シンボルが参照ハフマン・コード・テーブル2102を使用してハフマン・エンコードされた場合に出力されるであろう、ハフマン・コードの総ビット数である。つまり、LZ77エンジン102は、参照ハフマン・コード・テーブル2102を使用して、リテラル・シンボルごとにハフマン・コードのビット数を決定し、それらを加算して合計(サイズX)を作り出す。好ましくは、LZ77エンジン102のロジックは、好ましくは並行して、リテラルの参照ハフマン・コード・テーブル2102内でリテラル・シンボルの各々をルックアップして、各ハフマン・コードのビット数(例えば、図11Bのビット長1112)を決定し、それらを一緒に加算してサイズXを作り出す。一実施形態では、所定文字数、例えば、5以下の文字列に関してサイズXを決定するようにロジックが構成され、したがって、文字列が所定文字数より長い場合、下の判定ブロック2206で、サイズXがサイズYよりも大きいと仮定される。サイズYと呼ばれる第2のサイズは、一致した文字列(存在すると仮定する)へのバック・ポインタが参照ハフマン・コード・テーブル2102を使用してハフマン・エンコードされた場合に出力されるであろう、ハフマン・コードの総ビット数である。つまり、LZ77エンジン102は、参照ハフマン・コード・テーブル2102を使用して、追加ビットを含めてポインタの長さ及び距離の各々についてハフマン・コードのビット数(例えば、図11Bのビット長1112)を決定し、それらを加算して合計(サイズY)を作り出す。好ましくは、LZ77エンジン102のロジックは、好ましくは並行して、参照長さ及び距離ハフマン・コード・テーブル2102内で長さ及び距離シンボルの各々をルックアップして、各ハフマン・コードのビット数を決定し、それらを一緒に加算してサイズYを作り出す。
ここで図22を参照すると、データを圧縮するためのハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック2202から始まる。
ブロック2202で、LZ77エンジン102は、現在の検索ターゲット位置で文字列の一致を検索し、検出し、(例えば、ブロック302又はブロック1404に関して)前述したのと同様の方法で、現在の検索ターゲット位置から一致する文字列へのバック・ポインタを算出する。フローはブロック2204に進む。
ブロック2204で、LZ77エンジン102は、図21に関して前述したように、サイズX及びサイズYを決定する。つまり、LZ77エンジン102は、リテラル及びバック・ポインタの両方を事前ハフマン・エンコードして、そのそれぞれのハフマン・エンコードされたサイズを、ビット数を単位として決定する。フローは、判定ブロック2206に進む。
判定ブロック2206で、LZ77エンジン102は、サイズXがサイズYよりも小さいかどうかを判定する。小さい場合、フローはブロック2212に進み、そうでない場合、フローはブロック2208に進む。
判定ブロック2208で、LZ77エンジン102は、ブロック2202で算出されたバック・ポインタを生成する。つまり、LZ77エンジン102は、後でハフマン・エンコーディング・エンジン108によってハフマン・エンコードするために、バック・ポインタを(例えば、ブロック306又はブロック1406でのように)出力する。フローはブロック2214に進む。
ブロック2212で、LZ77エンジン102は、一致した文字列のリテラルを生成する。つまり、LZ77エンジン102は、後でハフマン・エンコーディング・エンジン108によってハフマン・エンコードするために、リテラルの指標を(例えば、ブロック306又はブロック1406でのように)出力する。フローはブロック2214に進む。
ブロック2214で、ハフマン・エンコーディング・エンジン108は、ブロック2208又はブロック2212で生成された出力、すなわち、一致した文字列のバック・ポインタ又はリテラルをハフマン・エンコードする。一実施形態では、ハフマン・エンコーディング・エンジン108は、参照ハフマン・コード・テーブル2102とは異なるハフマン・コード・テーブルを使用して、バック・ポインタ又はリテラルをハフマン・エンコードする。例えば、入力ブロックをハフマン・エンコードするためにハフマン・エンコーディング・エンジン108によって(例えば、ブロック1006、1434、1606、又は2006でのように)使用されるハフマン・コード・テーブルは、入力ブロックの初期部分がスキャンされた後に構築されたか(例えば、図16を参照)、又は選択された(例えば、図20を参照)ハフマン・コード・テーブルにすることができ、そのため、入力ブロックの初期部分がスキャンされている間は、サイズX及びサイズYを算出するために、参照ハフマン・コード・テーブル2102が使用されなければならない。つまり、参照ハフマン・コード・テーブル2102は、図22のブロック2202〜2212に従って実行される最適化が実行される時点で、既知でなければならない。最終的に入力ブロックをハフマン・エンコードするために使用されるハフマン・コード・テーブルとは異なるハフマン・コード・テーブルが使用されてサイズX及びサイズYを計算した場合でも、図22による動作は、依然として圧縮率を改善し、すなわち、図22による動作を使用しない従来方法よりも出力のサイズを削減することができる。フローはブロック2214で終了する。
好ましくは、図22による事前ハフマン・エンコーディングの動作は、複数の文字から成る入力ブロック全体のスキャンに対してLZ77エンジン102によって生成された各トークン212について実行される。ただし、以下で説明されているように、一部の実施形態では、事前ハフマン・エンコーディングは、例えばダイナミック−プライム・ハフマン・コード・テーブルを使用する場合に、初期部分がスキャンされた後の入力ブロックの残りの部分など、入力ブロックのスキャンの一部のみに対して生成されたトークン212に対して実行されることが可能である。
ここで図23Aを参照すると、一実施形態による図22のブロック2204の動作を表すフローチャートが示されている。フローはブロック2302で始まり、終了する。
ブロック2302で、LZ77エンジン102は、事前蓄積済みハフマン・コード・テーブルを使用してサイズX及びサイズYを決定する。事前蓄積済みハフマン・コード・テーブルは、ハードウェア・データ圧縮器100が複数の文字から成る入力ブロックの圧縮を開始する前に蓄積される。例えば、事前蓄積済みハフマン・コード・テーブルは、DEFLATE仕様によって規定された固定ハフマン・コード・テーブルにすることができ、そのリテラル/長さのテーブルは、基本的に下の表3(変更は括弧で示される)のように再現される。DEFLATE仕様では、固定ハフマン・コード・テーブルの距離コード0〜31は、(固定長)5ビット・コードと、場合によっては、上の表2に示すように、さらなるビットを使用して表されると規定されている。或いは、事前蓄積済みハフマン・コード・テーブルは、代表的な入力ブロック又は代表的な入力ブロックのサンプルのシンボルの頻度に基づいて構築されたハフマン・コード・テーブルにすることができる。一実施形態では、事前蓄積済みハフマン・コード・テーブルは、シンボル空間内のあらゆるシンボルのハフマン・コードを含む。代替の実施形態では、ハフマン・コード・テーブルは、シンボル空間の一部のシンボルのハフマン・コードを含まず、LZ77エンジン102は、それらのシンボルに対してサイズX及びサイズYを計算せず、判定ブロック2206での比較を実行せず、ブロック2208でバック・ポインタを生成する。
ここで図23Bを参照すると、代替の実施形態による図22のブロック2204の動作を表すフローチャートが示されている。フローはブロック2312で始まり、終了する。
ブロック2312で、LZ77エンジン102は、図14A〜20に関して前述したように構築されたダイナミック−プライム・ハフマン・コード・テーブルなどのダイナミック−プライム・ハフマン・コード・テーブルを使用して、サイズX及びサイズYを決定する。一実施形態では、図22の動作は、ダイナミック−プライム・ハフマン・コード・テーブルが(例えば、図16のブロック1604で)構築されるまでトークン212に対して実行されず、ダイナミック−プライム・ハフマン・コード・テーブルが構築される前に、LZ77圧縮エンジン102は、サイズX及びサイズYを計算してサイズX及びサイズYの関係に基づいてバック・ポインタの生成に関して選択的になるのではなく、ブロック2208でのように、単にバック・ポインタを生成する。代替の実施形態では、ダイナミック−プライム・ハフマン・コード・テーブルの構築前は、参照ハフマン・コード・テーブル2102が使用されてステップ2204を実行し、ダイナミック−プライム・ハフマン・コード・テーブルの構築後に、ダイナミック−プライム・ハフマン・コード・テーブルが使用されてステップ2204を実行する。
本明細書に記載された事前ハフマン・エンコーディングの実施形態の利点は、次のように説明されることが可能である。一部の従来方法では、LZ77圧縮アルゴリズムは、バック・ポインタで置換するための3バイト文字列の一致の検索を考慮しない。一方、本明細書に記載された実施形態は、場合によっては、3バイトの一致した文字列へのバック・ポインタの一部を(例えば、ブロック2208で)生成する。そのため、LZ77エンジン102のロジックが、ブロック2204の事前ハフマン・エンコーディング及びブロック2206の判定を実行し、それと並行して一致する文字列について入力ブロックの次のスキャンを行うように構成されている範囲において、本明細書に記載された実施形態は、より高い圧縮率を実現しながら、速度の低下を招かない。
異なるハッシュ・サイズにそれぞれ基づく複数の文字列一致検索ハッシュ・テーブル
LZ77方式の圧縮を実行する場合、検索ターゲット文字列の一致を検出するための入力ブロック内の後方検索に、非常に時間がかかる可能性がある。明らかな検索方法の1つは、入力ブロックの先頭から開始し、入力ブロック全体を1文字ずつ(現在の検索位置まで)移動し、最長の一致する文字列の位置を示すことである。しかし、この方法は極めて低速である。
さらに高速な方法は、ハッシュ・テーブルを使用することである。下でより詳細に説明されているように、入力ブロックがスキャンされると、ハッシュ・テーブルが構築されて使用され、入力ブロック内で検索される位置を減らす。つまり、ハッシュ・テーブルによって、一致を生む可能性の高い、すなわち、検索ターゲットの少なくとも少数の文字(例えば、3文字)を保持している可能性の高い入力ブロック内の位置に、検索の焦点を合わせることができる。これは、現在の検索ターゲット位置の前の入力ブロックの文字が、入力ブロックのスキャンの間に前に見られていることを利用して実現される。
例えば、現在の検索ターゲット位置の3文字が、ハッシュ・アルゴリズムに従ってハッシュされて、ハッシュ・テーブルのエントリのインデックスを指すインデックスを作り出す。ハッシュ・テーブルのエントリは、同じインデックスに対して以前にハッシュされた、入力ブロック内の位置へのポインタのハッシュ・チェーンの先頭である。これによって、検索ターゲット位置の3文字が、ポインタによって指し示された位置にもあるという相対的に高い見込みが(ハッシュ・アルゴリズム、ハッシュ・テーブルのサイズ、及び入力ブロックの文字の特徴に依存して)生まれる。これは、DEFLATE仕様のセクション4に記載されている。
一般的に言って、少なくとも一部の入力ファイル(例えば、ルイス・キャロル作の本「不思議の国のアリス」のテキスト)に対して4文字のハッシュを使用した場合、3文字のハッシュよりも出力ファイルが大きくなるが、より高速に出力ファイルを生成し、その他については同等になることが観察されている。出力ファイルが大きくなる理由は、多くの事例で、いくつかの3文字の一致が喪失されることにより、入力ブロックのリテラルをバック・ポインタに置換する機会が失われるという事実によって説明される。
速度の向上については、複数の要因の組み合わせによって説明される可能性がある。少なくとも1つの要因は、次のようにハッシュ・チェーン検索が短くなることが予想されることである。3文字の文字列「she」の37回の出現が、それまでの入力ブロックのスキャンで現れたと仮定する。37回の出現はすべて、3文字のハッシュ・テーブル内の同じハッシュ・チェーンに挿入される。37回出現した「she」のうちのいくつかの後に、別の文字が続いたと仮定し、例えば、「shea」が21回出現し、「shel」が12回出現し、「shed」が4回出現したと仮定する。これら3つの異なる4文字の文字列を、4文字のハッシュ・テーブルの3つの異なるハッシュ・チェーンに挿入する、4文字のハッシュ・アルゴリズムを仮定する。これは、4文字のハッシュ・テーブル内において「she」で始まる文字列の一致について検索されるハッシュ・チェーンが、3文字のハッシュ・テーブル内において検索されるハッシュ・チェーンよりも短くなる可能性が高く、その他の点については同じであるということを意味している。その他の点は、例えば、3文字のハッシュ・テーブル内の「she」と同じハッシュ・チェーンにハッシュされる、「she」以外の文字列との衝突を無視することや、4文字のハッシュ・テーブル内の「she」の後に「a」、「l」、及び「d」がそれぞれ続く文字列と同じ3つのハッシュ・チェーンにハッシュされる、別の文字が後に続く「she」以外の文字列との衝突を無視することである。
4文字のハッシュの速度と3文字のハッシュの出力サイズに近づく試みにおいて、ハードウェア・データ圧縮器100が2つのハッシュ・テーブルを維持する実施形態について説明する。1つは3文字のハッシュに基づくハッシュ・テーブルであり、もう1つは4文字のハッシュに基づくハッシュ・テーブルである。4文字のハッシュ・テーブルは、最初に少なくとも4文字の一致を検索するために使用され、3文字のハッシュ・テーブルは、4文字のハッシュ・テーブルを使用して4文字の一致が検出されなかった場合にのみ、少なくとも3文字の一致を検索するために使用される。一部の入力ブロックに対しては、4文字のハッシュ・テーブル内のハッシュ・チェーンがより短くなるため、一般に、より短いハッシュ・チェーンの検索は、より高速になることが可能である。しかし、必要に応じて3文字のハッシュ・テーブルが使用されるため、3文字のハッシュ・テーブルの圧縮率に近づくことが可能である。4文字のハッシュ・テーブルを使用して一致が検出された場合、3文字のハッシュ・テーブルを使用して検索する必要はないことが留意される。これは、一般的に言って、4文字のハッシュ・テーブルを使用して検出されるいかなる一致も、3文字のハッシュ・テーブルを使用して検出される一致と少なくとも同じ長さになるからである。
再びになるが、3文字のハッシュ・テーブルと4文字のハッシュ・テーブルとの目的は、3文字のハッシュ単独よりも高速化することと、4文字のハッシュ単独よりも圧縮率を高くすることとの双方である。説明のために、所与の入力ブロックに対して、時間の90%で4文字以上の一致が検出され、時間の10%のみで3文字の一致が検出されたと仮定する。この場合、圧縮器は、4文字のハッシュのみの実施形態では得られない、10%の3文字の一致による圧縮率の恩恵を受けるため、圧縮された出力は、通常、4文字のハッシュのみを使用した場合よりも小さくなるが、4文字のハッシュ・チェーンが統計的により短いため、各検索が統計的により高速になることにより、3文字のハッシュのみの実施形態よりも高速に出力を作り出す。
ここで図24を参照すると、図1のLZ77エンジン102の一部を表すブロック図が示されている。LZ77エンジン102は、4文字のハッシュ・テーブル2448を含む。4文字のハッシュ・テーブル2448は、4文字のハッシュ・テーブル・インデックス2444によってインデックスを指されるエントリの配列である。4文字のハッシュ・テーブル・インデックス2444は、4文字のハッシュ・アルゴリズムを使用して、4文字のハッシュ・テーブル・インデックス・ジェネレータ2442によって、複数の文字から成る入力ブロック2404の現在の検索ターゲット位置2402の4文字をハッシュして作り出される。4文字のハッシュ・アルゴリズムの一実施形態が、下の表5で説明されている。ただし、他の実施形態が企図されており、表5のハッシュ・アルゴリズムは、説明のための例として提供されている。一実施形態では、ハッシュ・アルゴリズムは、図39〜41に関して下で説明されているように、入力ブロック・タイプに依存する。4文字のハッシュ・テーブル・インデックス2444は、4文字値ではなく、4文字のハッシュ・テーブル2448へのインデックスであることが理解されるべきである(インデックス2444のサイズは、ハッシュ・テーブル2448のサイズに依存する)。4文字のハッシュ・テーブル2448の各エントリは、ノード2406のハッシュ・チェーン2441の先頭である。好ましくは、各ハッシュ・チェーン2441は、ノード2406のリンク・リストであるが、他の実施形態、例えば、配列、ツリーが企図される。各ノードは、チェーン2441内の次のノードへのポインタを含む。各ノードは、入力ブロック2404内の、現在の検索ターゲット位置2402の後方にある4文字の文字列の位置へのポインタをさらに含み、これら4文字の文字列は、4文字のハッシュ・テーブル2448内のエントリのインデックス2444の値に事前にハッシュされており、4文字のハッシュ・テーブル2448のハッシュ・チェーン2441は、ノード2406を含む。ノード2406の投入が、図25に関して下で詳細に説明される。図24に示されているように、各ハッシュ・チェーン2441の長さは、入力ブロック2404がスキャンされるときに変化することになり、一部のハッシュ・チェーン2441は、空である場合がある。一実施形態では、4文字のハッシュ・テーブル2448のエントリ数は16,384であるが、他の実施形態が企図される。
LZ77エンジン102は、3文字のハッシュ・テーブル2438をさらに含む。3文字のハッシュ・テーブル2438は、3文字のハッシュ・テーブル・インデックス2434によってインデックスを指されるエントリの配列である。3文字のハッシュ・テーブル・インデックス2434は、3文字のハッシュ・アルゴリズムを使用して、3文字のハッシュ・テーブル・インデックス・ジェネレータ2432によって、複数の文字から成る入力ブロック2404の現在の検索ターゲット位置2402の3文字をハッシュして作り出される。3文字のハッシュ・アルゴリズムの実施形態は、下の表4で説明されている。ただし、他の実施形態が企図されており、表4のハッシュ・アルゴリズムは、説明のための例として提供されている。一実施形態では、ハッシュ・アルゴリズムは、図39〜41に関して下で説明されているように、入力ブロック・タイプに依存する。3文字のハッシュ・テーブル・インデックス2434は、3文字値ではなく、3文字のハッシュ・テーブル2438へのインデックスであるということが理解されるべきである(インデックス2434のサイズは、ハッシュ・テーブル2438のサイズに依存する)。3文字のハッシュ・テーブル2438の各エントリは、ノード2406のハッシュ・チェーン2431の先頭である。好ましくは、各ハッシュ・チェーン2431は、ノード2406のリンク・リストであるが、他の実施形態、例えば、配列やツリーが企図される。各ノードは、チェーン2431内の次のノードへのポインタを含む。各ノードは、入力ブロック2404内の、現在の検索ターゲット位置2402の後方にある3文字の文字列の位置へのポインタをさらに含み、これら3文字の文字列は、3文字のハッシュ・テーブル2438内のエントリのインデックス2434の値に事前にハッシュされており、3文字のハッシュ・テーブル2438のハッシュ・チェーン2431は、ノード2406を含む。ノード2406の投入が、図25に関して下でより詳細に説明される。図24に示されているように、各ハッシュ・チェーン2431の長さは、入力ブロック2404がスキャンされるときに変化し、一部のハッシュ・チェーン2431は、空である場合がある。一実施形態では、3文字のハッシュ・テーブル2438のエントリ数は16,384であるが、他の実施形態が企図される。
一実施形態では、4文字のハッシュ・テーブル2448及び3文字のハッシュ・テーブル2438は、図1のハッシュ・メモリ103に格納される。別の実施形態では、ハードウェア・データ圧縮器100は、4文字のハッシュ・テーブル2448用及び3文字のハッシュ・テーブル2438用の別個のメモリを含む。一実施形態では、ハッシュ・チェーン2441/2431のノード2406は、ハッシュ・テーブル2438/2448のエントリとは別個のメモリに格納される。
下の表4及び5は、それぞれ3バイト・ハッシュ・アルゴリズム及び4バイト・ハッシュ・アルゴリズムの例である。
ここで図25を参照すると、図24のLZ77エンジン102の動作を表すフローチャートが示されている。フローは、ブロック2501及び2511から、好ましくは同時に、開始する。
ブロック2501で、4文字のハッシュ・インデックス・ジェネレータ2442が、入力ブロック2404内の現在の検索ターゲット位置2402の4文字をハッシュして、4文字のハッシュ・テーブル・インデックス2444を作り出す。フローはブロック2501からブロック2502に進む。
ブロック2511で、3文字のハッシュ・インデックス・ジェネレータ2432が、入力ブロック2404内の現在の検索ターゲット位置2402の3文字をハッシュして、3文字のハッシュ・テーブル・インデックス2434を作り出す。フローはブロック2511からブロック2502に進む。
ブロック2502で、LZ77エンジン102は、ブロック2501で作り出されたインデックス2444で、4文字のハッシュ・テーブル2448のハッシュ・チェーン2441を使用して、現在の検索ターゲット位置2402の文字列の一致について入力ブロック2404を検索する。つまり、LZ77エンジン102は、検索中断基準(例えば、使用されたノード2406の数、使用されたハッシュ・チェーン2441のパーセンテージ、又は一致した文字列の長さが所定値を超える)又はチェーン2441の末尾に達するまで、インデックスを指されたチェーン2441の先頭にあるノード2406によって指し示された入力ブロック2404の位置で一致について最初検索し、インデックスを指されたチェーン2441内の次のノード2406によって指し示された入力ブロック2404の位置でさらに長い一致について検索し、インデックスを指されたチェーン2441内のその次のノード2406によって指し示された入力ブロック2404の位置でさらに長い一致について検索する、というように動作する。フローは、判定ブロック2503に進む。
判定ブロック2503で、ブロック2502で一致が検出されていた場合、フローはブロック2504に進み、そうでない場合、フローはブロック2512に進む。
ブロック2504で、LZ77エンジン102は、検出された文字列の一致に対してバック・ポインタを生成する。フローは、ブロック2506及び2516に、好ましくは同時に、進む。
ブロック2506で、LZ77エンジン102は、ノード2406を、ブロック2501で作り出された4文字のハッシュ・テーブル2448のインデックス2444でハッシュ・チェーン2441に挿入する。このノード2406は、現在の検索ターゲット位置2402を指し示している。好ましくは、このノード2406はハッシュ・チェーン2441の先頭に挿入され、より新しいノード2406がより古いノード2406よりも先に検索されるようにし、このことは、バック・ポインタの距離値を減らす傾向がある。ただし、異なる順序のノード2406が維持される代替の実施形態が、図26〜35に関して下で説明される。フローはブロック2507に進む。
ブロック2507で、LZ77エンジン102は、現在の検索ターゲット位置2402を更新する。好ましくは、位置2402は、3文字のハッシュ・テーブル2438が使用される場合は3文字ずつ、4文字のハッシュ・テーブル2448が使用される場合は4文字ずつ進む。フローはブロック2507で終了する。
ブロック2512で、LZ77エンジン102は、ブロック2501で作り出されたインデックス2434で、3文字のハッシュ・テーブル2438のハッシュ・チェーン2431を使用して、現在の検索ターゲット位置2402の文字列の一致について入力ブロック2404を検索する。つまり、LZ77エンジン102は、検索中断基準(例えば、使用されたノード2406の数、使用されたハッシュ・チェーン2431のパーセンテージ、又は一致した文字列の長さが所定値を超える)又はチェーン2431の末尾に達するまで、インデックスを指されたチェーン2431の先頭にあるノード2406によって指し示された入力ブロック2404の位置で一致について最初検索し、インデックスを指されたチェーン2431内の次のノード2406によって指し示された入力ブロック2404の位置でさらに長い一致について検索し、インデックスを指されたチェーン2431内のその次のノード2406によって指し示された入力ブロック2404の位置でさらに長い一致について検索する、というように動作する。一実施形態では、検索中断基準は、3文字のハッシュ・テーブル2438の検索に対しては存在するが、4文字のハッシュ・テーブル2448の検索に対しては存在しない。フローは、判定ブロック2513に進む。
判定ブロック2513で、ブロック2512で一致が検出されていた場合、フローはブロック2514に進み、そうでない場合、フローはブロック2515に進む。
ブロック2514で、LZ77エンジン102は、検出された文字列の一致に対してバック・ポインタを生成する。フローは、ブロック2506及び2516に、好ましくは同時に、進む。
ブロック2515で、LZ77エンジン102は、現在の検索ターゲット位置2402でリテラル・シンボルを生成する。一実施形態では、LZ77エンジン102は3つのリテラル・シンボルを生成し、一方、別の実施形態では、LZ77エンジン102は4つのリテラル・シンボルを生成する。一実施形態では、生成されるリテラル・シンボルの数は、プログラム可能である。フローは、ブロック2506及び2516に、好ましくは同時に、進む。
ブロック2516で、LZ77エンジン102は、ノード2406を、ブロック2511で作り出された3文字のハッシュ・テーブル2438のインデックス2434でハッシュ・チェーン2431に挿入する。このノード2406は、現在の検索ターゲット位置2402を指し示している。好ましくは、このノード2406はハッシュ・チェーン2431の先頭に挿入され、より新しいノード2406がより古いノード2406よりも先に検索されるようにし、このことは、バック・ポインタの距離値を減らす傾向がある。ただし、異なる順序のノード2406が維持される代替の実施形態が、図26〜35に関して下で説明される。フローはブロック2507に進む。
3文字のハッシュ・テーブル及び4文字のハッシュ・テーブルを含む実施形態が説明されているが、実施形態はこれらに限定されないということが理解されるべきである。むしろ、さらに一般的に、M文字のハッシュ・テーブル及びN文字のハッシュ・テーブルが使用され、Mは2よりも大きく、NはMよりも大きい実施形態が企図される。したがって、例えば、3文字のハッシュ・テーブル及び5文字のハッシュ・テーブルを使用する実施形態が企図されたり、4文字のハッシュ・テーブル及び6文字のハッシュ・テーブルを使用する実施形態が企図されたりするなどである。
さらに、2つのハッシュ・テーブルを含む実施形態が説明されているが、実施形態は2つのハッシュ・テーブルに限定されないということが理解されるべきである。むしろ、さらに一般的に、J個のハッシュ・テーブルを含む実施形態が企図され、ここで、Jは1よりも大きい。したがって、例えば、3文字のハッシュ・テーブル、4文字のハッシュ・テーブル、及び6文字のハッシュ・テーブルを使用する実施形態が企図されたり、3文字のハッシュ・テーブル、5文字のハッシュ・テーブル、及び6文字のハッシュ・テーブルを使用する実施形態が企図されたりするなどである。ただし、複数のハッシュ・テーブルを有することは、通常、1つのハッシュ・テーブルよりも多くのメモリを必要とし、より高速な圧縮を実現するための望ましいトレードオフになる場合がある。
ノードの文字列の一致確率に基づくハッシュ・チェーンのソート
前述したように、LZ77エンジン102は、一致する文字列を検索してバック・ポインタを生成するとき、検索中断基準に達した場合、インデックスを指されたハッシュ・チェーン内の横断を打ち切ることができ、すなわち、ハッシュ・チェーンのすべてのノードを使用して検索するようハッシュ・チェーン全体を横断しなくてもよい。例えば、LZ77エンジン102は、長さが所定値を超える一致した文字列を検出したか、又は所定数のノードを使用して一致する文字列を検索したか、又はハッシュ・チェーンのノードのうちの所定パーセンテージを使用した後に、検索を停止することができる。これによって圧縮速度を向上することができるが、より長い文字列の一致が喪失される可能性があるため、圧縮率の低下を犠牲にする可能性がある。
一般的に言えば、長さがより長く、距離のより短いバック・ポインタを生成することで、圧縮率が向上する。長さがより長いと、入力ブロックのより多くの文字が置換されるため、圧縮率が向上する。距離がより短いと、より短い距離値のハフマン・コードについて必要な追加ビットはより少ないため、圧縮率が向上する。DEFLATE仕様は、距離がより短いと必要な追加ビットが減るため、ハフマン・エンコーディングによる圧縮を改善するために、小さい距離値を持つバック・ポインタを推奨している。DEFLATE仕様は、このことを、新しいノードをハッシュ・チェーンの先頭に挿入することによって実施する。つまり、この実装は、ハッシュ・チェーンのノードを、世代のみによって順序付ける。こうすることで、通常は、より距離の短いバック・ポインタが生成されるが、好ましくない、長さのより短いバック・ポインタが生成される場合もある。
検索中断基準に対する動機は、特定のハッシュ・チェーンが極めて長くなる可能性があるためである。例えば、入力ブロックが英語テキストであると仮定する。3文字の文字列「The」のハッシュ先のハッシュ・チェーンは、この文字列が入力ブロック内で頻繁に出現する可能性が高いため、相対的に長くなる可能性が非常に高い。しかし、一般的に言えば、「The」で始まる入力ブロック内のすべての位置が、その後の検索ターゲットとの一致を生み出す同じ確率を持っているわけではない。つまり、入力ブロック内には、「The」で始まり、且つその後に文字列の一致を生む可能性のある多くの異なる文字の組み合わせが続く、多くの異なる位置が存在する可能性が高く、上記の異なる組み合わせの各々は、一致を生み出す異なった見込みを有している。例えば、「Thez」、「Theq」、又は「Thej」を指し示すノードは、通常、「Ther」又は「Then」を指し示すノードよりも一致を生む可能性が低い。しかし、厳密に世代に従ってハッシュ・チェーン・ノードを順序付ける従来の実装では、「Thez」、「Theq」、及び「Thej」を指し示すノードは、相対的に新しく、ハッシュ・チェーン内で先に出現する、さらに具体的には、ハッシュ・チェーン内で検索中断ポイントよりも前の場所を占める可能性があり、「Ther」又は「Then」を指し示す一部のノードは、ハッシュ・チェーン内の検索中断ポイントよりも後ろの場所を占める可能性がある。したがって、「Ther」又は「Then」を指し示すノードがハッシュ・チェーン内の検索中断基準を超えて順序付けられた場合、LZ77エンジン102は、それらのノードにたどり着かず、それらのノードを使用しない可能性がある。
ここで図26を参照すると、一実施形態によるハードウェア・データ圧縮器100の一部を表すブロック図が示されている。ハードウェア・データ圧縮器100は、図1の入力ブロック・メモリ101、LZ77エンジン102、及びハッシュ・メモリ103を含む。複数の文字から成る入力ブロック2606は、入力ブロック・メモリ101に格納される。ハッシュ・チェーン2611(及び、図に示されていないが、ハッシュ・チェーン2611を指し示すハッシュ・テーブル)は、ハッシュ・メモリ103に格納される。ハッシュ・チェーン2611は、前述したハッシュ・チェーンと同様である。ただし、図26のハッシュ・チェーン2611は、確率2703を付加して強化されたノード2706(図27に関して下で説明される)を含む。LZ77エンジン102は、厳密に世代に従うのではなく、下で詳細に説明されているように、確率2703に従って、且つ等しい確率2703内では世代に従ってハッシュ・チェーン2611内のノード2706を有利に順序付けして、より長い一致した文字列を検出する見込みを改善することが可能である。
LZ77エンジン102は、互いに結合されたスキャン・エンジン2602及びチェーン・ソート・エンジン2604を含み、各エンジンは、入力ブロック・メモリ101及びハッシュ・メモリ103に結合される。一実施形態では、チェーン・ソート・エンジン2604は、ハッシュ・メモリ103へのスキャン・エンジン2602の接続を探って、スキャン・エンジン2602によってどのハッシュ・チェーン2611(例えば、ハッシュ・チェーンのインデックス)がアクセスされたかを検出する。それに応じて、チェーン・ソート・エンジン2604は、下でより詳細に説明されているように、スキャン・エンジン2602によって更新されたハッシュ・チェーン2611をソートする。
ここで図27を参照すると、図26のハッシュ・チェーン2611のノード2706を表すブロック図が示されている。ノード2706は、入力ブロック・ポインタ2702、確率2703、世代2704、及び次のポインタ(ネクスト・ポインタ)2705を含む。ネクスト・ポインタ2705は、チェーン2611内の次のノード2706を指し示す。入力ブロック・ポインタ2702は、図26の複数の文字から成る入力ブロック2606内の文字の位置を指し示し、この文字は、例えば、図28のブロック2802で説明されているように、ハッシュ・テーブルへのインデックスを作り出すために、隣接する文字(例えば、3文字の文字列)とともにハッシュされている。世代2704は、ノード2706が、ハッシュ・テーブルのその他のノード2706に対してどの程度最近作成されたかを示す。一実施形態では、次の世代(ネクスト世代)の値がカウンタで維持され、LZ77エンジン102が入力ブロックのスキャンを開始するときにゼロに初期化され、新しいノード2706が作成されるたびにインクリメントされる。この意味で、世代2704はシリアル・ナンバーに類似している。確率2703は、入力ブロック・ポインタ2702によって指し示された文字で始まる一致する文字列へのバック・ポインタがLZ77エンジン102によって生成されることになる見込みの相対的な指標である。チェーン・ソート・エンジン2604は、確率2703を使用して、ハッシュ・チェーン2611内のノード2706を順序付けして、より最適に一致する文字列を検出する見込みを有利に増やすことができる。以下では、動的確率の実施形態及び静的確率の実施形態が説明される。さらに、静的確率の実施形態は、ノード2706の確率2703の初期値を提供するために採用されることが可能であり、その後、この初期値は、動的確率の実施形態に従って更新されることが可能であると理解されるべきである。
ここで図28を参照すると、動的ノード確率の実施形態による、新しいノードをハッシュ・チェーンに挿入するための図26のハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック2802から始まる。
ブロック2802で、スキャン・エンジン2602は、現在の検索ターゲット位置で3文字をハッシュして、ハッシュ・テーブル・インデックスを作り出す。図24及び25に関して前述された文字数などの、異なる文字数がハッシュされる他の実施形態が企図される。フローはブロック2804に進む。
ブロック2804で、チェーン・ソート・エンジン2604は、新しいノード2706を作成し、入力ブロック・ポインタ2702に現在の検索ターゲット位置を代入し(populates)、確率2703にゼロの値を代入し、世代2704にネクスト世代レジスタの現在の値を代入し、それから、ネクスト世代レジスタをインクリメントする。好ましくは、スキャン・エンジン2602が、現在の検索ターゲット位置などの、新しいノード2706を作成するために必要な情報をチェーン・ソート・エンジン2604に提供する。代替の実施形態では、スキャン・エンジン2602が新しいノード2706を作成し、チェーン・ソート・エンジン2604に通知する。フローはブロック2806に進む。
ブロック2806で、チェーン・ソート・エンジン2604は、新しいノード2706を、ブロック2802で作り出されたハッシュ・テーブル・インデックスでハッシュ・チェーン2611に挿入する。好ましくは、チェーン・ソート・エンジン2604が、ゼロの確率2703を有する最も先の(すなわち、最も先頭に近い)ノード2706(ここでは、ノードXと呼ぶ)を検出し、新しいノード2706のネクスト・ポインタ2705に、ノードXを指し示すように代入し、ノードXを指し示していたノード2706のネクスト・ポインタ2705(ノードXがチェーン2611の先頭にあった場合は、先頭ポインタであり得る)を、新しいノード2706を指し示すように更新する。代替の実施形態では、スキャン・エンジン2602が、新しいノードをハッシュ・チェーン2611の先頭に挿入し、ハッシュ・チェーン2611をソートすること、すなわち、新しいノード2706をハッシュ・チェーン2611内の適切な位置に配置することが必要であることを、チェーン・ソート・エンジン2604に通知する。フローはブロック2806で終了する。
ここで図29を参照すると、図28による図26のハードウェア・データ圧縮器100の動作を例で表すタイミング図が示されている。図29において、時間は下向きに流れ、ノード2706が、それらの世代2704及び確率2703の値とともに示されている。入力ブロック・ポインタ2702は図に示されていないが、各ノード2706からの矢印は、そのノードのネクスト・ポインタ2705が指すノードを示している。最初の行において、1回目では、ハッシュ・チェーン2611は5つのノードを含んでいる。2の世代2704の値及び3の確率2703の値を持つノード2706がチェーン2611の先頭にあり、1の世代2704の値及び2の確率2703の値を持つノード2706がそれに続き、4の世代2704の値及び0の確率2703の値を持つノード2706がそれに続き、3の世代2704の値及び0の確率2703の値を持つノード2706がそれに続き、0の世代2704の値及び0の確率2703の値を持つ最後のノード2706がそれに続いている。
1回目の後の2回目では、5の世代2704の値及び0の確率2703の値を持つ新しいノード2706が(例えば、ブロック2804でのように)作成される。新しいノード2706は、4の世代2704の値を持つノード2706が、ゼロの確率2703の値を持つチェーン2611内で最も先のノード2706だったため、1の世代2704の値を持つノード2706と、4の世代2704の値を持つノード2706との間に(例えば、図28のブロック2806でのように)挿入される。
ここで図30を参照すると、動的ノード確率の実施形態による、ハッシュ・チェーンをソートするための図26のハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック3002から始まる。
ブロック3002で、スキャン・エンジン2602は、入力ブロック2606内の文字の一致する文字列を検出する。この一致する文字列は、ブロック2802で作り出されたインデックスによってインデックスを指されたハッシュ・チェーン2611内の、ノード2706(ここでは、ノードKと呼ぶ)の入力ブロック・ポインタ2702によって指し示された位置で始まる。つまり、その一致する文字列は、現在の検索ターゲット位置によって指し示された文字で始まる入力ブロック2606内の文字の文字列に一致する。それに応じて、スキャン・エンジン2602は、一致する文字列へのバック・ポインタ、すなわち、長さ及び距離の順序付けされた対を生成する。好ましくは、一致する文字列は、例えば、バック・ポインタの距離が所定しきい値以下になる、又は中断条件が与えられた場合に検出される最長の長さになるなどの、所与の制限の下での最適な一致になるように、LZ77エンジン102によって考慮される。フローはブロック3004に進む。
ブロック3004で、スキャン・エンジン2602は、ノードKの確率2703をインクリメントする。代替の実施形態では、チェーン・ソート・エンジン2604は、スキャン・エンジン2602がチェーン・ソート・エンジン2604に必要な情報、例えば、ノードKの位置を提供することに応答して、確率2703をインクリメントする。フローはブロック3006に進む。
ブロック3006で、チェーン・ソート・エンジン2604は、インクリメントされた確率2703に基づいて、ノードKを含むハッシュ・チェーン2611をソートする。さらに具体的には、チェーン・ソート・エンジン2604は、ノードKの確率2703がハッシュ・チェーン2611内のノードKの前のノード2706よりも大きい限り、ノードKをハッシュ・チェーン2611内のより先の位置に(すなわち、ハッシュ・チェーン2611の先頭に向かって)移動する。それから、チェーン・ソート・エンジン2604は、ノードKの確率2703がハッシュ・チェーン2611内のノードKの前のノード2706と等しく、且つノードKの世代2704がノードKの前のノード2706より新しい限り、ノードKをハッシュ・チェーン2611内のより先の位置に移動する。ここで、ネクスト世代2704の値をインクリメントする実施形態では、第1のノード2706が、第2のノード2706の世代2704の値よりも大きい世代2704の値を持っている場合、第1のノード2706が第2のノード2706よりも若い/新しいことに注意する。フローはブロック3006で終了する。
ここで図31を参照すると、図30による図26のハードウェア・データ圧縮器100の動作を例で表すタイミング図が示されている。図31において、時間は下向きに流れ、ノード2706は、それらの世代2704及び確率2703の値とともに示されている。入力ブロック・ポインタ2702は図に示されていないが、各ノード2706からの矢印は、そのノードのネクスト・ポインタ2705が指すノードを示している。最初の行において、1回目では、ハッシュ・チェーン2611は3つのノードを含んでいる。0の世代2704の値及び3の確率2703の値を持つノード2706がチェーン2611の先頭にあり、1の世代2704の値及び2の確率2703の値を持つノード2706がそれに続き、2の世代2704の値及び1の確率2703の値を持つ最後のノード2706がそれに続いている。
その後、スキャン・エンジン2602は、例えば図30のブロック3002で、ノード2(すなわち、2の世代2704の値を持つノード2706)の入力ブロック・ポインタ2702を使用して、文字列の一致に基づいてバック・ポインタを生成する。1回目の後の2回目では、2番目の行に示すように、スキャン・エンジン2602がノード2の確率2703の値を1から2にインクリメントする。それに応じて、チェーン・ソート・エンジン2604は、例えば図30のブロック3006で、ノード2と、ノード2の前のノード2706であるノード1(すなわち、1の世代2704の値を持つノード2706)との、ハッシュ・チェーン2611内での場所を交換する。これは、2番目の行でも示されているように、現在、ノード2がノード1と同じ確率2703の値(2)を有しており、ノード2がノード1よりも新しいからである。
その後、2回目、スキャン・エンジン2602は、ノード2の入力ブロック・ポインタ2702を使用して、文字列の一致に基づいてバック・ポインタを生成する。2回目の後の3回目では、3番目の行に示すように、スキャン・エンジン2602がノード2の確率2703の値を2から3にインクリメントする。それに応じて、チェーン・ソート・エンジン2604は、ノード2と、ノード2の前のノード2706であるノード0(すなわち、0の世代2704の値を持つノード2706)との、ハッシュ・チェーン2611内での場所を交換する。これは、3番目の行でも示されているように、現在、ノード2がノード0と同じ確率2703の値(3)を有しており、ノード2がノード0よりも新しいからである。
ここで図32及び33を参照すると、図33に示されたルックアップ・テーブル3302を作成するための方法を表すフローチャートが図32に示されており、このルックアップ・テーブル3302は、静的なハッシュ・チェーン・ノード確率の実施形態で使用される。好ましくは、図32に関して説明される方法は、自動化された方法、例えば、ソフトウェアで実行される。好ましくは、ハードウェア・データ圧縮器100による複数の文字から成る入力ブロックの圧縮の前に、ユーザ(例えば、ハードウェア・データ圧縮器100の製造業者又はエンド・ユーザ)がこの方法を実行する。例えば、この方法は、製造業者によって実行され、ハードウェア・データ圧縮器100とともにエンド・ユーザに提供されることが可能である。或いは、製造業者がルックアップ・テーブル3302を作成し、その後、エンド・ユーザが製造業者からルックアップ・テーブル3302をダウンロードする。或いは、ハードウェア・データ圧縮器100を使用してエンド・ユーザが頻繁に圧縮するファイルに合わせて調整されたカスタム・ルックアップ・テーブル3302を、エンド・ユーザ自身が作成する。この場合、好ましくは、製造業者がエンド・ユーザに、この方法を具現化するソフトウェアを提供する。一実施形態では、ルックアップ・テーブル3302は、テーブル・メモリ107内に格納されるが、ルックアップ・テーブル3302が他のメモリの1つ(例えば、101、103、又は105)に格納される他の実施形態が企図される。一実施形態では、ルックアップ・テーブル3302は、連想記憶装置(content−addressable memory:CAM)に格納され、このCAM内で、図33の4文字の文字列3303は入力アドレスと比較される内容であり、CAMは、一致する文字列3303に対応するスコア3304を出力し、一致が検出されない場合、CAMは失敗のインジケータとしてtrue値を発生させる。フローは、ブロック3202から始まる。
ブロック3202で、ユーザ(例えば、製造業者、又はサーバ・ファーム管理者などのエンド・ユーザ)は、その後ハードウェア・データ圧縮器100によって圧縮される入力ブロックの代表になることを期待する、複数の文字から成る入力ブロックのセットを収集する。例えば、英語テキストの場合、ユーザは数百の英語の作品から入力ブロックのセットを収集できる。別の例では、ユーザは多くのHTMLファイル、オーディオファイル、又は画像ファイルから入力ブロックのセットを収集できる。その後ユーザは、入力ブロックのセット内で最も頻繁に出現するJ個の4文字の文字列、及びこれら4文字文字列の各々の出現頻度をリストにまとめる。Jは、相対的に大きい整数(例えば、500〜5,000)であり、ルックアップ・テーブル3302のサイズに割り当てることができる所望のメモリ量、及びノード2706の確率2703に基づくハッシュ・チェーン2611のソートに起因する文字列一致検索の効率向上による所望のスピードアップに依存する。フローはブロック3204に進む。
ブロック3204で、ユーザは、ブロック3202で蓄積されたテーブルのJ個の4文字の文字列の各々について、LZ77エンジン102によって採用される(例えば、図24の3文字のハッシュ・インデックス・ジェネレータ2432によって採用される)同じハッシュ・アルゴリズムを使用して文字列の最初の3文字をハッシュして、文字列のインデックスを作り出す。したがって、このインデックスは、その後LZ77エンジン102によって作り出されることが可能であり、ハッシュ・メモリ103内のハッシュ・テーブルへのインデックス(例えば、図24の3文字のハッシュ・テーブル2438への3文字のハッシュ・テーブル・インデックス2434)と同じ値を持つ。フローはブロック3206に進む。
ブロック3206で、ユーザは、ブロック3204で作り出された各インデックス値について、J個の文字列のうち、その先頭3文字がインデックスにハッシュされている文字列の各グループについて、グループ内の文字列の頻度を調べ、グループの各文字列の、グループの他の文字列に対する頻度に基づいて、グループの各文字列にスコアを割り当てる。例えば、4つの文字列が同じインデックスにハッシュされ、ブロック3202により、それぞれ8、11、98、及び16の頻度を持ったと仮定する。次にユーザは、最低のスコアを第1の文字列に、次に低いスコアを第2の文字列に、最高のスコアを第3の文字列に、次に高いスコアを第4の文字列に割り当てる。例えば、1、2、4、3である。その後、これらスコアは、例えば、ブロック3208で、ルックアップ・テーブル3302に代入するために使用されることが可能である。これらの4文字の文字列が、後でハードウェア・データ圧縮器100によって圧縮される複数の文字から成る入力ブロック内で出現した場合、ノード2706がそれらに対して作成され、ハッシュ・チェーン2611に挿入され、下でより詳細に説明されているように、チェーン・ソート・エンジン2604が、ルックアップ・テーブル3302内の上記スコアを利用して、ハッシュ・チェーン2611をソートする。フローはブロック3208に進む。
ブロック3208で、ユーザは、ブロック3202で蓄積された4文字の文字列及びブロック3206で割り当てられたそれらに関連するスコアのルックアップ・テーブル3302を作成する。その例が、図33に示されている。ルックアップ・テーブル3302は、図33で配列として示されているが、ツリーやハッシュ・テーブルなどのさまざまな形態で配置されることも可能である。ルックアップ・テーブル3302は、図34及び35に関して下で説明されているように、確率2703をハッシュ・チェーン2611のノード2706に割り当てるために使用されることが可能である。フローはブロック3208で終了する。
ここで図34を参照すると、静的なノード確率の実施形態による、ハッシュ・チェーンをソートするための図26のハードウェア・データ圧縮器100の動作を表すフローチャートが示されている。フローは、ブロック3402から始まる。
ブロック3402で、スキャン・エンジン2602は、現在の検索ターゲット位置で3文字をハッシュして、ハッシュ・テーブル・インデックスを作り出す。フローはブロック3404に進む。
ブロック3404で、チェーン・ソート・エンジン2604は、新しいノード2706を作成し、入力ブロック・ポインタ2702に現在の検索ターゲット位置を代入し、世代2704にネクスト世代レジスタの現在の値を代入し、その後、ネクスト世代レジスタをインクリメントする。好ましくは、スキャン・エンジン2602が、現在の検索ターゲット位置などの、新しいノード2706を作成するために必要な情報をチェーン・ソート・エンジン2604に提供する。代替の実施形態では、スキャン・エンジン2602が新しいノード2706を作成し、チェーン・ソート・エンジン2604に通知する。フローはブロック3406に進む。
ブロック3406で、チェーン・ソート・エンジン2604は、入力ブロック2606の現在の検索ターゲット位置の3文字(すなわち、ブロック3402でハッシュされた3文字)及び隣接する次の文字で構成された4文字の文字列を受け取る。フローはブロック3408に進む。
ブロック3408で、チェーン・ソート・エンジン2604は、ブロック3406で作成された4文字の文字列の、ルックアップ・テーブル3302内の文字列3303の1つとの一致を検索する。一致が検出された場合、チェーン・ソート・エンジン2604は、新しいノード2706の確率2703に、一致する文字列3303に関連付けられたスコア3304を割り当て、一致が検出されない場合、チェーン・ソート・エンジン2604は、新しいノード2706の確率2703に、ゼロの値を割り当てる。フローはブロック3412に進む。
ブロック3412で、チェーン・ソート・エンジン2604は、新しいノード2706を、ブロック3402で作り出されたインデックスでハッシュ・チェーン2611に挿入する。チェーン・ソート・エンジン2604は、ハッシュ・チェーン2611内の他のノード2706に対する確率に基づいて、新しいノード2706を挿入する。具体的には、チェーン・ソート・エンジン2604は、新しいノード2706を、ハッシュ・チェーン2611内の低い確率2703を持つノード2706よりも先で、高い確率2703を持つノード2706よりも後に挿入する。等しい確率2703のノード2706について、チェーン・ソート・エンジン2604は、より新しいノード2706を、相対的により古いノード2706の前に順序付ける。したがって、現在最新のノード2706である新しいノード2706は、それと同じ確率2703を持つ他のすべてのノード2706の前に挿入される。フローはブロック3412で終了する。
ここで図35を参照すると、図34による図26のハードウェア・データ圧縮器100の動作を例で表すタイミング図が示されている。図35において、時間は下向きに流れ、ノード2706は、世代2704及び確率2703の値とともに示されている。入力ブロック・ポインタ2702は図に示されていないが、各ノード2706からの矢印は、そのノードのネクスト・ポインタ2705が指すノードを示している。最初の行において、1回目では、ハッシュ・チェーン2611は5つのノードを含んでいる。2の世代2704の値及び8の確率2703の値を持つノード2706がチェーン2611の先頭にあり、1の世代2704の値及び6の確率2703の値を持つノード2706がそれに続き、4の世代2704の値及び5の確率2703の値を持つノード2706がそれに続き、3の世代2704の値及び1の確率2703の値を持つノード2706がそれに続き、0の世代2704の値及び0の確率2703の値を持つ最後のノード2706がそれに続く。
1回目の後の2回目では、5の世代2704の値及び1の確率2703の値を持つ新しいノード2706が(例えば、ブロック3404〜3408でのように)作成される。新しいノード2706は、4の世代2704の値を持つノード2706と、3の世代2704の値を持つノード2706との間に(例えば、図34のブロック3412で)挿入される。これは、4の世代2704の値を持つノード2706が、新しいノード2706よりも大きい確率2703の値を有しており、新しいノード2706は、3の世代2704の値を持つノード2706と等しい確率2703の値を有し、且つ3の世代2704の値を持つノード2706よりも新しいからである。
3文字がハッシュされ、ルックアップ・テーブル3302の文字列3303の長さが4文字である実施形態が説明されているが、ハッシュされる文字数が3よりも大きく、文字列の長さが4よりも長い他の実施形態が企図される。ただし、その実施形態では、ハッシュされる文字の後に続く1つ又は複数の文字を決定するために、文字列の長さの文字数はハッシュの文字数よりも多い。
図26〜35の説明から観察できるように、ハッシュ・チェーン2611の各ノード2706は、その確率2703に従って順序付けされることが可能である。その場合、入力ブロック2606内の文字で始まる一致する文字列へのバック・ポインタは、スキャン・エンジン2602が中断基準に達する前に、世代のみによって順序付けされたハッシュ・チェーン2611を使用して検出されるであろう文字列よりも長い一致する文字列が検出され、それにより圧縮率ができれば改善されることになる見込みが増えることを期待して、スキャン・エンジン2602によって生成される。図28〜31に関連する実施形態は、入力ブロック2606のスキャンの間、一致する文字列を検出してバック・ポインタを生成するためにノード2706がより頻繁に使用されるとき、ノード2706の確率2703が増えることが可能な動的スキームを採用しており、一方、図32〜35に関連する実施形態は、ノード2706の確率2703が、入力ブロックの代表的なサンプル内の文字列の頻度についての事前解析に基づいて割り当てられる、静的スキームを採用している。
LZ77エンジンからのトークンを直接ハフマン・エンコードするハードウェア・データ圧縮器
ファイルを圧縮してインターネットを経由して転送するWebサーバなどのサーバの利用が急増するにつれて、そのようなサーバで使用するためのハードウェア・データ圧縮器の必要性も急増する可能性が高い。その結果、低コスト且つ低消費電力のハードウェア・データ圧縮器に対する需要が促進される可能性がある。
ここで図36を参照すると、代替の実施形態によるハードウェア・データ圧縮器3600を表すブロック図が示されている。ハードウェア・データ圧縮器3600は、図1のハードウェア・データ圧縮器100と同様に、入力ブロック・メモリ101、LZ77エンジン102、ハッシュ・メモリ103、ハフマン・エンコーディング・エンジン108、及び出力メモリ109を含む。下でより詳細に説明されているように、ハードウェア・データ圧縮器3600は、トークン3612を直接ハフマン・エンコーディング・エンジン108に供給し、ハフマン・エンコーディング・エンジン108は、各トークン3612が受信されると、それらを直ちにハフマン・エンコードし、結果として生じるハフマン・コードを出力メモリ109に書き込む。したがって、ハードウェア・データ圧縮器3600は、バック・ポインタ・メモリ105を含む必要がない。さらに、事前蓄積済みハフマン・コード・テーブルが採用されるため、図1のソート・エンジン104もハフマン・コード・テーブル構築エンジン106も、ハードウェア・データ圧縮器3600に含まれる必要がない。本明細書に記載された代替モードでの動作の間、ハードウェア・データ圧縮器3600において、バック・ポインタ・メモリ105(及び、ソート・エンジン104とハフマン・コード・テーブル構築エンジン106)が存在しないか、又は少なくとも使用されないことによって、図1の実施形態などの他の実施形態よりもコスト、サイズ、及び消費電力を有利に削減することができる。
一実施形態では、ハフマン・エンコーディング・エンジン108はCAMを備え、CAMにおいて、ハフマン・コード・テーブルのシンボル値は、ハフマン・エンコードされる入力シンボルと比較される内容であり、CAMは、一致した入力シンボルに対応するハフマン・コードを出力する。好ましくは、CAMは、3つのリテラル・シンボルがトークン3612に関連付けられた場合、又はバック・ポインタのトークン3612の長さ及び距離がCAMに入力された場合に対応するために、3つのシンボル入力を同時に受信し、3つのそれぞれのハフマン・コードを同時に出力するように構成される。LZ77エンジン102が入力ブロックのスキャンを開始する前に、事前に蓄積されたリテラル/長さ及び距離のハフマン・コード・テーブルが、CAMにロードされる。好ましくは、CAMへの3つの入力の各々が、LZ77エンジン102によって提供される関連付けられた信号を有し、該信号は、シンボルがリテラル/長さであるか、又は距離であるかを示し、CAMがリテラル/長さハフマン・コード・テーブルにアクセスすべきか又は距離ハフマン・コード・テーブルにアクセスすべきかを決定できるようにする。好ましくは、バック・ポインタの長さ及び距離の追加ビットは、LZ77エンジン102から渡され、CAMによって出力された値と共に適切に順序付けされ、出力メモリ109に書き込まれる。
ここで図37を参照すると、図36のハードウェア・データ圧縮器3600の動作を表すフローチャートが示されている。図37において、LZ77エンジン102はブロック3702及び3704で動作し、ハフマン・エンコーディング・エンジン108はブロック3712及び3714で動作する。フローは、ブロック3702から始まる。
ブロック3702で、LZ77エンジン102は入力ブロックをスキャンし、入力ブロック内の現在の検索ターゲット位置で文字列の一致を検索する。フローはブロック3704に進む。
ブロック3704で、LZ77エンジン102は、ハフマン・エンコーディング・エンジン108に対してトークン3612を生成し、現在の検索ターゲット位置を更新する。フローはLZ77エンジン102に関するブロック3702に戻って(ブロック終結文字に直面するまで)次の文字列を検索し、同時に、フローはハフマン・エンコーディング・エンジン108に関する判定ブロック3712に進む。
判定ブロック3712で、ハフマン・エンコーディング・エンジン108は、LZ77エンジン102がハフマン・エンコーディング・エンジン108のためのトークン3612を生成したかどうかを決定する。生成していた場合、フローはブロック3714に進み、生成していない場合、LZ77エンジン102がトークン3612を生成するまでは、フローは判定ブロック3712に戻る。
ブロック3714で、ハフマン・エンコーディング・エンジン108は、LZ77エンジン102から受信されたトークン3612の各シンボルについて、シンボルをハフマン・エンコードし、ハフマン・コードを出力メモリ109に書き込む。フローは判定ブロック3712に戻る。
有利なことに、ハフマン・エンコーディング・エンジン108は、LZ77エンジン102がブロック3702及び3704で動作を実行する時間と同様の時間をかけてブロック3712及び3714で動作を実行するように構成される。つまり、LZ77エンジン102によって生成される連続する各トークン3612間の時間は、トークン3612を受信してハフマン・エンコードし、結果として生じるハフマン・コードを出力メモリ109に書き込むためにハフマン・エンコーディング・エンジン108によって必要とされる時間を上回るか、又は等しい。したがって、トークン3612を中間的な格納のためのメモリに書き込む必要がなく、トークン3612をメモリから読み出す必要がない。
ここで図38を参照すると、図37の方法による図36のハードウェア・データ圧縮器3600の動作を表すタイミング図が示されている。上側部分はLZ77エンジン102の動作を示し、下側部分はハフマン・エンコーディング・エンジン108の動作を示している。時間は左から右に進んでいる。図に示されている時間はクロック・サイクルを表しているが、ナノ秒などの、関連する他の時間単位が企図される。
図に示されているように、サイクル0でLZ77エンジン102が、(例えば、図37のブロック3702でのように)現在の検索位置での入力ブロックのスキャンを開始して、文字列の一致の最初の検索(S1で示される)を実行し、サイクル3でトークン3612(TOK1で示される)をハフマン・エンコーディング・エンジン108に出力する。それに応じて、ハフマン・エンコーディング・エンジン108は、(例えば、図37のブロック3714でのように)TOK1に関連付けられたシンボルの各々をハフマン・エンコードし、結果として生じたハフマン・コードを出力メモリ109に書き込む。この動作は、LZ77エンジン102がその次の検索(S2)を終了し、サイクル10で2番目のトークン(TOK2)を出力する前に、サイクル6で終了する。それに応じて、ハフマン・エンコーディング・エンジン108は、TOK2に関連付けられたシンボルの各々をハフマン・エンコードし、結果的に生じたハフマン・コードを出力メモリ109に書き込む。この動作は、LZ77エンジン102がその次の検索(S3)を終了し、サイクル13で別のトークン(TOK3)を出力する前に、サイクル13で終了する。それに応じて、ハフマン・エンコーディング・エンジン108は、TOK3に関連付けられたシンボルの各々をハフマン・エンコードし、結果的に生じたハフマン・コードを出力メモリ109に書き込む。この動作は、LZ77エンジン102がその次の検索(S4)を終了し、サイクル72で別のトークン(TOK4)を出力する前に、サイクル16で終了する。それに応じて、ハフマン・エンコーディング・エンジン108は、TOK4に関連付けられたシンボルの各々をハフマン・エンコードし、結果的に生じたハフマン・コードを出力メモリ109に書き込む。この動作は、LZ77エンジン102がその次の検索(S5)を終了し、サイクル75で別のトークン(TOK5)を出力する前に、サイクル75で終了する。それに応じて、ハフマン・エンコーディング・エンジン108は、TOK5に関連付けられたシンボルの各々をハフマン・エンコードし、結果的に生じたハフマン・コードを出力メモリ109に書き込む。この動作は、サイクル78で終了する。
図37に示されているように、トークン3612を生成するためにLZ77エンジン102によって必要とされるクロック・サイクル数は変化する可能性があり、例えば、S4は59クロック・サイクルを必要とし、通常これは比較的長いハッシュ・チェーンを示し、一方、S1、S3、及びS5は3クロック・サイクルしか必要とせず、通常これはハッシュ・チェーンが空だったことを示す。それにもかかわらず、有利なことにハフマン・エンコーディング・エンジン108は、LZ77エンジン102によって生成された各トークン3612に関連付けられたシンボルを、各トークンが生成されたときにハフマン・エンコードし、それにより、バック・ポインタをメモリに書き込む必要性又はこれらをメモリから読み出す必要性を有利に軽減する。
一実施形態では、約25KBのメモリが、図1に関して説明されたような実施形態で節約される。この実施形態では、バック・ポインタ及びフラグ・メモリ105が、約8Kx24ビットのバック・ポインタと16Kx1ビットのフラグとを保持するように構成されている。
一実施形態では、ハードウェア・データ圧縮器100は、(例えば、図3〜20に関して前述したモードなどの、他のモードで動作するために)バック・ポインタ及びフラグ・メモリ105を含む。ただし、図36〜38に関して説明されるモードで動作する場合、そのような実施形態では、メモリ・ハードウェアの節約は実現されないが、それでもなお、電力の節約は実現されることが可能である。これは、電力が、LZ77エンジン102によるメモリへのバック・ポインタ及びフラグの書き込みによって消費されず、ハフマン・エンコーディング・エンジン108によるメモリからのバック・ポインタ及びフラグの読み出しによっても消費されないからである。
入力ブロック・タイプに基づく動的ハッシュ・アルゴリズムを使用したハードウェア・データ圧縮器
図24のハッシュ・インデックス・ジェネレータ2432及び2442などのハッシュ・インデックス・ジェネレータによって使用されるハッシュ・アルゴリズムを作成する際に考慮すべき目標の1つは、ハッシュ・テーブル上のハッシュ・インデックスの分布をできるだけ相対的に均一にすることである。そうすることで、非常に長いハッシュ・チェーンが発生する見込みが減るか、又は少なくとも問題を悪化させない傾向があり、LZ77エンジン102のスキャンに関連した一致する文字列の検索時間を改善することができる。これは少なくとも、ある程度は、ハッシュのエイリアシング又はハッシュの衝突の概念に起因する。ハッシュのエイリアシングは、異なる入力が同じハッシュ・インデックスにハッシュされた場合に生じる。例えば、ハッシュ・アルゴリズムに依存して、文字「the」は文字「was」と同じインデックスにハッシュされる場合がある。これは、例えば、英語テキストでは「the」及び「was」が頻繁に出現する傾向があり、そのインデックスのハッシュ・チェーンが非常に長くなる可能性があるため、ほとんどの英語テキストの入力ブロックにとって特に望ましくない。
上の例からわかるように、一般的な英単語が異なるインデックスにハッシュされる傾向がある英語テキスト用のハッシュ・アルゴリズムが存在することは有利である。ただし、ハードウェア・データ圧縮器100は、英語テキスト以外のタイプの入力ブロックを圧縮するために使用されることが可能である。したがって、話されない/記述される言語(例えば、HTML、Javaなど)を含むその他の言語のための、相対的に均一なハッシュ・インデックスの分布を生成する傾向があるハッシュ・アルゴリズムが存在することは有利である。さらに、非言語タイプ(例えば、スプレッドシート、実行可能バイナリ・ファイルなど)を含むその他の入力ブロック・タイプのための、相対的に均一なハッシュ・インデックスの分布を生成する傾向があるハッシュ・アルゴリズムが存在することは有利である。
ここで図39を参照すると、図1のLZ77エンジン102の一部を表すブロック図が示されている。図39〜41の実施形態では、圧縮される入力ブロックの種類を示すために、入力ブロック・タイプ3901(例えば、テキスト、スプレッドシート、ワード・プロセッサ、PDF、HTML、Javaなど)がハードウェア・データ圧縮器100に提供され、LZ77エンジン102が、入力ブロック・タイプ3901に依存して異なるハッシュ・アルゴリズムを採用する。一部の実施形態では、ハッシュされるビットの数は、入力ブロック・タイプ3901によって変化する。例えば、入力ブロック・タイプがASCIIテキストである場合、各文字(バイト)の上位ビットはハッシュに含まれず、例えば、24ビットでなく21ビットがハッシュされる。例えば、図41を参照されたい。一般的に言えば、上位ビットは常にゼロであり、分布を歪める可能性があるため、上記のことは、より良好な分布を提供する。他の実施形態では、ハッシュ・アルゴリズムによって実行される算術/論理演算が、入力ブロック・タイプによって変化する。さらに、他の実施形態では、ハッシュ・アルゴリズムによってハッシュされる入力ブロックの文字の数が、入力ブロック・タイプによって変化する。
LZ77エンジン102は、ハッシュ・テーブル3948とノード3906のハッシュ・チェーン3941とを含む。ハッシュ・テーブル3948、ハッシュ・チェーン3941、及びノード3906は、図24、26、及び27のハッシュ・テーブル、ハッシュ・チェーン、及びノード2448、2438、2431、2441、2611、2406、及び2706と同様とすることが可能である。ハッシュ・テーブル3948は、MUX3999の出力であるインデックス3944によってインデックスを指される。MUX3999は、入力ブロック・タイプ・インジケータ3901を制御入力として受信する。入力ブロック・タイプ3901に基づき、MUX3999は、複数のインデックス3954−A、3954−B、及び3954−C(個々を一般化して3954と呼び、且つまとめて3954と呼ぶ)のうちの1つを選択して、インデックス3944として出力する。複数のインデックス3954の各々は、それぞれのハッシュ・テーブル・インデックス・ジェネレータ3942−A、3942−B、及び3942−C(個々を一般化して3942と呼び、且つまとめて3942と呼ぶ)によって作り出される。ハッシュ・テーブル・インデックス・ジェネレータ3942の各々は、現在の検索ターゲット位置3902で、複数の文字から成る入力ブロック3904の最初の文字3936(例えば3)をハッシュするが、そのそれぞれのインデックス3954を生成するために、アルゴリズムA、アルゴリズムB、及びアルゴリズムCと呼ばれる異なるハッシュ・アルゴリズムを各々が使用する。一実施形態では、1つ又は複数のハッシュ・アルゴリズムは、図24及び25に関して前述したハッシュ・アルゴリズム、つまり、3バイト・ハッシュ・アルゴリズム及び4バイト・ハッシュ・アルゴリズムにすることができる。
ここで図40を参照すると、図39のLZ77エンジン102の動作を表すフローチャートが示されている。フローは、ブロック4002から始まる。
ブロック4002で、MUX3999は入力ブロック・タイプ3999を受信する。フローはブロック4004に進む。
ブロック4004で、ハッシュ・テーブル・インデックス・ジェネレータ3942の各々は、それぞれ異なるハッシュ・アルゴリズムを使用して最初の文字3936をハッシュして、MUX3999に提供されるそれぞれのインデックス3954を生成し、MUXは、入力ブロック・タイプ3901に基づいて、インデックス3954のうちの1つを選択してインデックス3944として出力する。こうして、MUX3999は、入力ブロック・タイプ3901に基づいて、ハッシュ・アルゴリズムのうちの1つを効率的に選択する。フローはブロック4006に進む。
ブロック4006で、ブロック4004で作り出されたインデックス3944は、ハッシュ・テーブル3948のインデックスを指してハッシュ・チェーン3941のうちの1つを選択するために使用され、その選択されたハッシュ・チェーン3941をLZ77エンジン102が使用して、現在の検索ターゲット位置3902によって指し示された入力ブロック3904の位置で始まる文字列の一致について、上記選択されたハッシュ・チェーン3941のノード3906によって指し示された位置で入力ブロック3904内を検索する。フローはブロック4006で終了する。
ここで図41を参照すると、図39のハッシュ・インデックス・ジェネレータ3942のうちの1つをより詳細に表すブロック図が示されている。図41のハッシュ・インデックス・ジェネレータ3942は、そのハッシュ・アルゴリズムにおいて、入力ブロック3936からの文字のすべてのビットを使用するわけではないという点が、他と異なっている。さらに具体的には、図に示されているように、ハッシュ・インデックス・ジェネレータ3942は、入力ブロック3936の3文字(図41では、第1の文字、第2の文字、及び第3の文字で示される)の、3文字の各々の最上位ビット(most significant bit:MSB)を除くあらゆるビットを受信し、そのハッシュ・アルゴリズムで使用する。ハッシュ・インデックス・ジェネレータ3942は、図に示されている21ビット、すなわち、第1の文字、第2の文字、及び第3の文字のそれぞれの下位7ビットをハッシュして、図39のMUX3999に提供されるインデックス3954を作り出す。下の表6は、図41のハッシュ・インデックス・ジェネレータ3942によって21ビットをハッシュするために使用されるハッシュ・アルゴリズムの例である。ただし、他の実施形態が企図されており、表6のハッシュ・アルゴリズムは、説明のための例として提供されている。さらに、入力ブロック3936の文字のすべてのビットよりも少ない、各文字の下位7ビット以外のビットがハッシュされる他の実施形態が企図される。図41の実施形態は、特に、各文字(バイト)の上位ビットがゼロになる傾向があって、それによりハッシュ・インデックスの分布が不均一になりやすい、ASCIIテキストの入力ブロック・タイプ3901に適している可能性がある。
ここで図42を参照すると、図1などのハードウェア・データ圧縮器100を含むシステム4200を表すブロック図が示されている。システム4200は、システム・バス4204によってメモリ4206、ハードウェア・データ圧縮器100、及び他のペリフェラル4208に接続されたプロセッサ4202を含む。プロセッサ4202は、システム・バス4204を介してコマンドをハードウェア・データ圧縮器100に送信する。好ましくは、ハードウェア・データ圧縮器100は、I/O空間にマッピングされる制御及びステータス・レジスタ(control and status registers:CSR)を含み、このCSRによってプロセッサ4202が、複数の文字から成る入力ブロックを圧縮するためなどのコマンドを送信する。或いは、CSRは、I/Oではなくメモリにマッピングされることも可能である。さらに、好ましくは、ハードウェア・データ圧縮器100のメモリの1つ又は複数がメモリ空間にマッピングされる。特に、入力ブロック・メモリ101、出力メモリ109、及びテーブル・メモリ107は、プロセッサ4202によって書き込み可能及び/又は読み出し可能にすることができる。例えば、プロセッサ4202は、圧縮されるべき複数の文字から成る入力ブロックをシステム・メモリ4206から入力ブロック・メモリ101に書き込む(又は、ダイレクト・メモリ・アクセス(direct memory access :DMA)動作に、この書き込みを実行させる)ことができ、プロセッサ4202は、ハードウェア・データ圧縮器100が入力ブロックの圧縮を終了したときに、圧縮された出力ブロックを出力ブロック・メモリ109からシステム・メモリ4206に読み出す(又は、ダイレクト・メモリ・アクセス(DMA)動作に、この読み出しを実行させる)ことができる。或いは、プロセッサ4202は、ハードウェア・データ圧縮器100に、複数の文字から成る入力ブロックのシステム・メモリ4206内のアドレスを提供することができ、ハードウェア・データ圧縮器100は、そのアドレスを入力ブロック・メモリ101に読み出す(又は、ダイレクト・メモリ・アクセス(DMA)動作に、この読み出しを実行させる)ことができ、プロセッサ4202は、ハードウェア・データ圧縮器100に、圧縮されたブロックを書き込ませたいシステム・メモリ4206内のアドレスを提供することができ、ハードウェア・データ圧縮器100は、入力ブロックの圧縮を終了したときに、圧縮されたブロックを出力ブロック・メモリ109からそのアドレスに書き込む(又は、ダイレクト・メモリ・アクセス(DMA)動作に、この書き込みを実行させる)ことができる。さらに、プロセッサ4202は、前述した事前に蓄積されたテーブル及び/又は「参照」テーブルなどのハフマン・コード・テーブルを、(前述した方法と同様の方法のうちの1つで)テーブル・メモリ107に代入することができる。
ここで図43を参照すると、代替の実施形態によるハードウェア・データ圧縮器100を含むシステム4300を表すブロック図が示されている。図43のシステム4300は、図42のシステム4200に類似している。ただし、図43のシステム4300では、プロセッサ4302はハードウェア・データ圧縮器100を備える。つまり、ハードウェア・データ圧縮器100は、プロセッサ4302のアーキテクチャ的な機能ユニットである。プロセッサ4302は、命令セット・アーキテクチャ(instruction set architecture:ISA)内に命令を含み、プロセッサ4302上で実行されるソフトウェアは、上記命令を実行して、ハードウェア・データ圧縮器100を制御したり、ハードウェア・データ圧縮器100にアクセスしたりすることができる。一実施形態では、プロセッサ4302は、ソース・オペランドとデスティネーション・オペランドと制御オペランドとが含まれるCOMPRESS BLOCK命令を含む。ソース・オペランドは、圧縮されるべき複数の文字から成る入力ブロックのシステム・メモリ4206内の位置を指定し、デスティネーション・オペランドは、圧縮されたブロックが書き込まれるべき位置を指定し、制御オペランドは、データ圧縮を実行するためにハードウェア・データ圧縮器100によって必要とされる制御情報を指定する。例えば、制御情報は、速度を圧縮率よりも優先するかどうか、及び/又は速度を圧縮率よりもどの程度優先するかを示すパラメータを含むことができる。そのパラメータに応じて、ハードウェア・データ圧縮器100は、同時的なシンボル・リストのソートを採用するか否か;ダイナミック−プライム・ハフマン・コード・テーブルを採用するか否か;一致する文字列を生成するか又はバック・ポインタを生成するかを決定するための事前ハフマン・エンコーディングを採用するか否か;2つのハッシュ・テーブルを採用するか否か;ノードの文字列の一致確率に基づくハッシュ・チェーンのソートを採用するか否かであって、採用する場合、静的優先順位アプローチ又は動的優先順位アプローチを採用するか否か、さらに静的優先順位アプローチを使用する場合は、ルックアップ・テーブルを採用するか否か;入力ブロック・タイプに基づく複数のハッシュ・アルゴリズムからの選択を採用するか否か;及び/又は、LZ77エンジンからの出力トークンの直接ハフマン・エンコーディングを採用するか否かを判定することができる。或いは、制御情報は、上記の各々について別個のパラメータを含む。他のパラメータには、例えば、DEFLATE仕様によって規定される固定ハフマン・コード・テーブル、「参照」ハフマン・コード・テーブルを含む事前蓄積済みハフマン・コード・テーブル、ダイナミック−プライム・ハフマン・コード・テーブルを使用するかどうかなどの、使用されるハフマン・コード・テーブルに関する情報を含むことができる。
本明細書では本発明のさまざまな実施形態が説明されているが、これらの実施形態は例として提示されており、これらに限定されないということが理解されるべきである。関連するコンピュータ分野の当業者にとって、本明細書における形態及び詳細のさまざまな変更が、本発明の範囲を逸脱することなく行われることが可能であるということは明らかである。例えば、ソフトウェアは、本明細書に記載された装置及び方法の機能、製造、モデリング、シミュレーション、記述、及び/又はテストなどを可能にすることができる。これは、一般的なプログラミング言語(例えば、C、C++)、Verilog HDL、VHDLなどを含むハードウェア記述言語(HDL)、又は他の使用可能なプログラムの使用を通じて実現可能である。そのようなソフトウェアは、磁気テープ、半導体、磁気ディスク若しくは光ディスク(例えば、CD−ROM、DVD−ROMなど)、ネットワーク、有線、無線、又は他の通信媒体などの、コンピュータが使用できる任意の既知の媒体に配置されることが可能である。本明細書に記載された装置及び方法の実施形態は、(例えば、HDLで具現化又は規定された)プロセッサ・コアなどの半導体IPコア(intellectual property core)に含まれ、集積回路の製造においてハードウェアに変換されることが可能である。さらに、本明細書に記載された装置及び方法は、ハードウェアとソフトウェアの組み合わせとして具現化されることが可能である。したがって、本発明は、本明細書に記載された実施形態例によって限定されるべきではなく、以下の特許請求の範囲及びその均等物のみに従って定義されるべきである。具体的には、本発明は、汎用コンピュータで使用できるプロセッサ・デバイス内に実装されることが可能である。最後に、当業者は、本発明と同じ目的を実行するために、添付された特許請求の範囲によって定義された本発明の範囲を逸脱することなく、開示された概念及び特定の実施形態を、他の構造を設計又は変更するための基礎として容易に使用できることを理解するであろう。