クラスターギャップ

以下の記事から分離/再編集

本題とずれていた、なが~い愚痴は別記事に分離→ 大容量のデータを処理する作業をしていたのだが、256GBしか内部ストレージが...

大量のデータ

昨今は画像処理やAIというものが出てきたため、凄まじい量の画像データを処理する必要が出てきた。今手元にあるデータは4TB・・・4000GBにもなる。

これらのデータは全てが使用するデータではない。使うところだけ計測したら良さそうなものであるが、もしかすると使うつもりが無い所のデータも後から必要になるかもしれないということで、殆ど取りっぱなしにしている。(これは経験上そういうことが多々あったのだ)

さて、プログラムで処理を掛けたり、データをザッピングするにしても、不要な部分を取り除きたいわけで、特定の条件に従ってデータを要るところだけ集める作業をやっている。

偉い人は「そんなん、お前が一生懸命プログラムと睨めっこするのを待ってるより、庶務とか派遣を動員して、人力でやったほうが早いで」とかまぁ言うんだが・・・データ4TBもあるんですぜ旦那。画像なら一枚0.1MBとかのものが、4TB分もあるですわ。
4TBって4,000GBで、それはつまり4,000,000MBなわけですよ。つまり40,000,000枚くらいあるわけ。

1枚平均1秒で仕分けしたとして、11,111時間かかるわけですよ。単純計算で。
1人にやらせたら1カ月の平均労働時間は160時間だから、残業無しとして69カ月かかりますよと。69か月って5.7年だからね。俺もうこの会社にいるか分かりませんぜって話。
二人入れても半分の2.8年だし、10人でやったって半年かかる。つーか、1万時間って最低賃金で人を使っても1,000万円掛かる。

実際には1枚平均1秒より早く仕訳けられそうな気はする。例えば操業が止まっているタイミングの画像データを捨てるんだったら、運転データと1枚1枚付き合わせなくたって、休憩時間に当たりを付けて、スタートとエンドを探して、ガバッと消せばいい。1時間で大体4万データくらいあるから、この作業で40,000データを処理できるわけだ。上の計算だと40,000データにかかる作業時間の見積もりは11時間だけど、絶対にそんなにかからない。せいぜい・・・15分くらいか?

だからまぁ、1枚平均1秒っていう見積もりの信ぴょう性は怪しいが・・・
でも、止まっている時間というのは決まっていないものも多いし、24時間運転だから夜~朝みたいにバッサリは捨てられない。
それに、計測データが特定の条件の時は対象としないとかがあるから、計測データも数列とはいえ確認せねばならない。あと露光オーバーの画像を抜いたりとか・・・

そういうのもあるから、1枚1秒という見積もりが過剰とも言い切れない。もしかすると過少かもしれない。
ま、そんなわけで、この令和でAIな時代に、そんなバカバカしい人海戦術は辞めましょうよと、上を諭すのも私の給料の内という訳だ。やれやれ。


データ容量は小さいハズなのに、足りなくなる空き容量

そうしてプログラムを処理しているのだが、この画像データであるということ特有の問題に悩まされた。というのも、画像処理を掛けるためのデータというのは、スマホで取った写真とかに比べると非常に小さい。人間が見るわけじゃないから、画質とサイズは必要なくって、特に見えるべきところがドアップで最低限の細かさで映ってりゃいいからだ。

なので、先ほども触れたが0.1MBとかの画像が、つまり小さい画像がものすごい大量にある。
ここで、パソコンのHDDの仕組みの話になるのだが、パソコンでデータを扱う際はクラスタサイズというものを考慮しなくてはいけない。

というのも、パソコンの内部でファイルが物理的にHDDのどこに保存されているのかは、アドレスで識別している。アドレス=住所。まんまだな。
イメージとしては目次として考えるとよい。このファイルの先頭は何ページ目と書いてあるようなものだ。

大昔のコンピュータは1BYTEごとにアドレスを振っていた。ところが、昨今は数TBとか言う世界になってきた。
1TB=1,000,000MB=1,000,000,000,000BYTEなわけだ。1BYTE単位で管理したら、先頭の1BYTEのアドレスは1だが、1TB目のアドレスが1,000,000,000,000になってしまう。
すると、どのファイルがどのアドレスだよと管理するためのデータがとんでもなくでかくなる。仮にアドレスの番号を4BYTEにしたとしても、4,294,967,295までしか表現できないからもっと必要で、上の例だと5BYTEは必要になる。

すると、1,000,000,000,000BYTEのデータを保管するのに必要なアドレスデータが5,000,000,000,000BYTEになるという、先のたとえでいえば本文より何倍も目次がデカいということになる。

そこで考え出されたのがクラスタだ。データ自体は1BYTE単位で扱えるが、アドレスはもっと大きいくくり、例えば1,000BYTE単位で扱うようにしよう。というわけだ。
上の例でいえば、アドレスは0~1,000,000,000の範囲だけで良くなるから4BYTEで良いし、覚えておかなけれならないアドレスも1,000,000,000個しかないから、4,000,000,000BYTEで足りる。

ここで、データは必ずしも1,000BYTE単位じゃないよねって話が出てくる。例えば987 BYTEとか、1,234BYTEのデータもあるよねって。その場合は、987BYTEでも1クラスタ=1,000BYTE占有したことにするし、1,234BYTEのデータなら2クラスタ=2,000BYTE使う。
するとデータが書けない半端な部分が生じてしまうけど、これはもう諦めようって考え方。この部分をクラスタギャップという。

なので、クラスタサイズは大きくした方が大容量データに適するけれど、あんまり大きくするとクラスタギャップによる使えない領域が増えて損になる、というトレードオフの関係にある。

クラスタサイズは時代によって変わっていて、現代では2MBくらいである。

すると、先の例では0.1MBしかなかったファイルが、HDD上では2MB消費してしまうわけだ。このようにクソ無駄なことになる。このため、回避策として0.1MBのファイル10万個とかを1個のZIPファイルに圧縮している。
圧縮することで概念的に連続した一個の大きい―データとして扱うので、HDDに書き込まれる際には内部のファイル間のギャップは生じないのだ。


このようにしてあの手この手で頑張っているのだが、先の通りデータをふるいに掛けようとしたときに厄介なことになる。一個ずつ展開して中身を分けないといけないからだ。

これは幸い、解凍せずに特定のデータを抽出する手法があるのでそれを利用している。

なので作ったプログラムは、まずデータを保管している巨大なサーバーのストレージから、適当なデータZIPを1個だけゴロっと出してきて、中身を分析する。そして必要と判断したデータだけを抜き取って、ローカルにコピーしていく。コピーし終わったらそれをZIP圧縮して、抽出したデータとしてストレージに入れる。そういう作業を延々と繰り返すようにした。

とっころがだ、データは一定期間ごとにZIPを作るようにしたので、稼働の状況により1個がデカいファイルができた。こいつを処理するときは、ローカルに一時的に置かれるデータの量が多くなってしまう。なんせ全部処理してから圧縮して移動するからな。

すると、プログラムが走っているのが、256GBしかストレージが無い子供のおもちゃみたいなPCだと、容量が不足して処理できなくなってしまう。プログラムを工夫するべきかもしれないが、まずは要らないデータが無いか四苦八苦し始めた。