Logitech Trackman Marble の代替機

Logitech (Logicool) の Trackman Marble というトラックボールがある。

机が散らかっている人に御用達しなトラックボールだ。

ボタンのスイッチの強度が弱かったり、頑なにスクロールウィールが実装されなかったりと色々と足りないが、Logicool製品の安定したボールの操作性には病みつきになる。

ただし、ここ最近は生産がされていない様子で、ネットショップでも数万円単位のぼったくり価格になっていることが多く、Trackman Marble難民が発生している。

大手トラックボールメーカーの ケンジントン・テクノロジー・グループのトラックボールも試してみたが、加工精度が悪いのかボールの回転に引っ掛かりがあり、痛い目にあった。

GameBall Trackball もゲーミング用に設計された中央ボールトラックボールで興味はあるのだが、諸事情により日本には出荷していないので輸入代行を使わないと手に入らない。

GameBall. The gaming trackball mouse.

 

個人的なおすすめの代替機は SANWA の GRAVIトラックボールマウスだ。

direct.sanwa.co.jp

direct.sanwa.co.jp

 

メリット:

  • ボール中央型なので Trackman Marble からの移行は楽
  • スクロールウィールがある。
  • ボタンが多く、カスタマイズ可能なので最初は左右ボタンだけにしておいて、指の動きが慣れた真ん中専用ボタンの配置等ができる
  • 有線モデルと無線モデルがある。

デメリット

  • ボタンカスタマイズには専用ソフト (Windowsのみ) が読み込まれている必要があり、専用ソフト無しでは標準構成となる。
  • ボールが若干大きめ。
  • 光学センサー部分に透明カバーが無いため埃がたまると急に反応しなくなることがある(ふーふーして解消)

とりあえずはコレで良いんじゃないかな、という感じ。

Minesweeper と解くプログラムを考えてみる

Steam 上で 14 Minesweper Variants というゲームがあるがこれがなかなか面白い。

store.steampowered.com

ゲームの中身については Youtube の Gate 氏の動画がとても参考になる。

www.youtube.com

再生リスト:

https://www.youtube.com/watch?v=eGTILDZnMzs&list=PLmyjj-hv7yVGBKjp7YDr4zwDL-JAp7py_

一般的 (Vanilla) ルールもあれば、マスの価値の判断基準が違ったり、マスが判定する視野やフィールド全体単位の判定等もあってなかなか刺激的である。 14 Minesweeper Variants を解くプログラムを書くとしたらどのような作戦になるのかを考えてみた。

まず大前提が、Minesweeper を解くとしたら人間のように各数字マスに注目して切り分けを行うか、それとも爆弾配置を総当たりするかの方法になる。 14 Minesweeper Variants では一つのボード上で複数のルールが飛び交うことになるので今回は総当たりで実装することにする。

爆弾配置の総当たりは簡単に言えば「二進数 n ビットの配列のうち、1 が立っている状態が m 個あるものを全て作れ」という案件だ。

盤面が全て同じルールで構成される場合は「最初の部分が違反していたので類似パターンは全て省略」といった最適化が可能だが、 14 Minesweeper Variantsでは複数のルールが飛び交うためそう簡単にはいかない。

爆弾配置の総当たり計算 k-permutations

ビット配列の総当たりは "k-permutations" というアルゴルズムだ。この場合の "k" は規模可変、という意味らしい。

最近は 仕事で "k-anonymity" (k-匿名性) も使っているので "k-" さんにはとてもお世話になっているような気がする。他には "T-近似性" や "L-多様性" のような類似命名があるそうな。

<?php
    function k_permutatons($remaining_bits, $length, $bit_array = Array()) {
        if ($remaining_bits == 0) {
            // 残りマスは全て 0
            yield array_merge($bit_array, array_fill(0, $length, 0));
        } else if ($remaining_bits == $length) {
            // 残りマスは全て 1
            yield array_merge($bit_array, array_fill(0, $length, 1));
        } else {
            // 今回は 1 のパターン
            k_permutations($remaining_bits -1, $length -1, array_merge($bit_array, Array(1)));
            // 今回は 0 のパターン
            k_permutations($remaining_bits   , $length -1, array_merge($bit_array, Array(0)));
        }
    }

14 Minesweeper Variants の場合、5x5 の爆弾数は 10個、 6x6 の爆弾数は14個、7x7 の爆弾数は20個、8x8 の爆弾数は 26個だ。 ゲーム開始序盤の空きマスが圧倒的に多い状態で 32bit以下とは言っても総当たりを計算して、その上で各生成盤面の正当性の確認をするとなると膨大な処理能力が必要となる。

GPU等を使った並列処理ができれば簡単かもしれないが、本件は処理ルールが複雑なので整理も兼ねてシングルスレッドで実装方法を検討する。

※ 実際には bit array の受け渡しはせず、「爆弾配置可能場所候補」順にマッピングした盤面を直に渡すと良いだろう。

Point of Interest の導入

爆弾配置の総当たりをする場合、配置先のマスが一つ増えると計算するパターンは倍加する。 5x5 や 6x6 ならまだ数分以内で計算可能だが、それ以上の盤面だと計算の負荷が上がりすぎるため Point of Interest を導入して配置マスを減らすのだ。

結局爆弾の配置の全パターンを計算するにしても、配置が有効であるかのチェックは数字が判明しているマス目の周辺しか行わない。それ以外のマス目の爆弾配置は一切処理されないのだ。最初にそれぞれのマス目から見える範囲を確認し、その見える範囲だけの爆弾配置を計算すれば良い。

 
3
1
 
?31

POIを使わない場合は爆弾配置可能マスは 20マスだが、POIを使う場合は10マスだ。ゲーム序盤ではとても役に立つことだろう。

ただし、Point of Interest の導入を行うと配置可能マスが減る関係でk permutationsの「残りマスは全て1」が誤発動するようになるのでこの最適化は行えない。

各マスの処理ルールの確定

14 Minesweeper Variants の場合は最初は盤面全体が同じルールだが、ゲームが進むと複合ルール化したり、各マスで適用されるルールが違ったりと難易度が変わる。 ゲーム内にある各ルールを個別に処理として実装すると実装量が増えるのでルールを整理する必要がある。

ルールを整理すると以下がわかる(一部)。

  • 探索範囲、集計方法に影響するもの

    • Vanilla: 3x3の中の爆弾数量を判定する
    • Wall: 3x3の中で爆弾壁の長さを判定する
    • Partition: 3x3 の中で爆弾壁の数を判定する
    • Xross: 縦横各方向2マスを判定する
    • Eyesight: 縦横全マス + 自分自身を判定する
  • 計算結果に影響を及ぼすもの

    • Negate: 白マスを 1、 黒マスを -1 で計算する
    • Multiple: 白マスを 2、黒マスを 1 で計算する
    • Lie: 演算結果と予想数が 1 ずれる
  • 盤面全体に影響を及ぼすもの

    • Quad: 2x2 マスの中は必ず爆弾が存在する
    • Connect: 全ての爆弾マスが8方向で隣接する
    • Three: 各方向で爆弾が3マス連続で並ばない
  • 計算結果に影響を及ぼすものだけがルールと指定されている場合は集計方法は Vanilla がそのまま使用できる。

  • Lie の判定方法は簡単だ。 abs(予想数 - 実際の数) が 0 か 1 になるかの判定で良い。Lie は予想数が一個の場合にしか使えないので Wall と Partition では使えない。
  • 盤面全体に影響を及ぼすものは計算負荷が高いので一番最後に判定するために取り分けておく。

探索ルートの策定

k-permutations で爆弾の配置を総当たりで生成した後で盤面の判定処理を行うが、この判定処理を行う回数は最も多い。つまり一回分の処理の最適化が数万倍に効果を出すのだ。 n x n マスの毎回ループして判断対象を探すのはとても無駄なので、探索ルートを事前いきめて、そのルートで指定されたマスのみの判断を行うようにする。

探索ルートの決め方には前述の Point of Interest が強く関わってくる。

  • 特定のマス目の Point of Interest の中に爆弾設置可能な空白がある場合はそれが「爆弾設置可能候補」としてマーキングされるのだが、そういった数字マスが探索ルートとなる。
  • PoI の全てが既に配置済みのマスや、マス目の数字が ? のものは除外される。
  • PoI に既に爆弾が配置済みの場合や数字マス(安全が確定)の場合は情報を事前に処理しても良い。

探索ルートの各項目は以下のような値となる

  • x 軸座標
  • y 軸座標
  • 適用ルール
  • 適用効果 (白マスの価値、黒マスの価値、結果の差分)
  • 処理対象の PoI マス一覧
  • 判定の初期値 (PoIマスを事前処理した場合は初期値を設定し、PoIマスを減らしておく)
  • 処理負荷(未処理PoIマスの数量)

探索ルートの値をきめたら処理負荷(未処理PoIマスの数量)等でソートしておく。処理負荷でソートするならなら盤面全体の判定も探索ルートに含めても良い。

全体のフロー

全体のフローとしては以下のような流れになる。

準備段階

  • 各マス目に適用されるルールを整理する。
    • 爆弾の検出範囲を影響するもと、計算結果を影響するものと、盤面全体に影響するものとで分類する。
  • 各マス目においての定石パターンを確認し、埋められるものは埋める。
  • 各マス目の Point of Interest 範囲を特定する
  • Point of Interest 範囲に空白が存在する場合は爆弾配置候補としてマーキングし、中央マスを探索ルートに追記する。

探索段階

  • k permutations を用いて爆弾を候補地に総当たりで配置する。
    • 探索ルートから処理ルールや座標の情報を取り出す。
      • 1マス分の判定処理を行う
    • 全マスが判定を通過したら盤面全体のチェック処理を行う。
    • 盤面が有効な場合は「爆弾設置率」「爆弾未設置率」の統計データに加える。

探索完了後

  • 各マスの爆弾設置/未設置の統計を確認し、どちらかが 100% になるものを「爆弾確定マス」「安全確定マス」として出力する。

Turing Pi 2 で Jetson Nano から TX2 NX にレベルアップした際に困ったこと。

Turing Pi 2 は NVIDIA Jetson / Raspberry Pi Compute Module 4 を4台クラスタ構成できに Mini-ITX マザーボード

turingpi.com

 

注意事項:

  • RTC回路が 1.5V仕様なのに初期ロットには CR2032 (3V) のバッテリーホルダがついており、CR2032を入れると過電流でBMCが起動しない。バッテリーホルダに 1.5V電池を装着するアダプターが開発される予定なのでRTCを使う場合はそれを待つこと。
  • ノード1 からノード 4 でそれぞれ使えるインターフェースが異なっているので注意すること。
  • ノード1 のみが HDMI / MIPI DSI 2レーン(Raspberry Pi と同じ)外部出力があるが、HDMIから出力する前にDIPスイッチを Jetson / CM4 に合わせて設定する必要がある。DIPスイッチには薄い黄色のフィルムが貼ってあるのでフィルムを剥がすところから始めよう。つまようじおすすめ。
  • 注文時にNVMeオプションを付けると背面にM.2 NVMeのコネクタが実装された状態で納品される。NVMeオプションを付けない場合は自力ではんだ付けすること。
  • NVMeは片面実装の 2260か 2280を使用できる。両面実装のものを使う場合は M2 スタンドオフを使う。

    https://www.amazon.co.jp/gp/product/B08FT789F2/

困ったこと:

  • Jetson Nano 開発キット B01 から入門して Jetson TX2 NX にステップアップしようとするとファームウェアの初期化で詰まる。
    1. Jetson TX2 NX は digi-key 等から購入できる。ヒートシンク(必須)は別売なので注意すること。尚、ヒートシンクのファンは 51℃以上で回りだす仕様。注文すると米国から爆速配送される。

    2. Jetson Nano 開発キット B01 の Jetson NanoモジュールはMicroSDカード仕様なので外部から書き換えは容易だが、Jetson TX2 NX は eMMC なのでキャリアボード経由でリカバリモードでの初期化が必要。いろんなSBC (シングルボードコンピューター) はリカバリモードでは emmcをUSB接続するだけだが、Jetsonでは独自プロトコル
    3. Jetson Nano 開発キット B01 はピンアサインが異なり、 TX2 NX は非対応。正規品では Jetson Xavier NX 開発キットが必要で、予算的(16万円+)に詰む。
    4. 「reComputer J202 Nano/Xavier NX用キャリアボード」が全種類対応していて、Nano B01と寸法が同じなのでこれを使う(23,000円程度)。尚、電源は5.5mm/2.1mmの12V。筆者は内蔵SATA電源をバレル端子に変換するアダプタを使った。

      reComputer J202 Jetson Nano/Xavier NX用キャリアボード(ACアダプタ抜き)www.switch-science.com

    5. リカバリボタンを押しながら電源ボタンを押して起動、みたいなことをするので試験用スイッチと、電源投入時の自動起動を防止するジャンパーを用意しておくこと。

      https://files.seeedstudio.com/wiki/reComputer/reComputer-J202-carrier-board-datasheet.pdf

  • Jetson Nano / Jetson TX2 のファームウェアの書き込み環境を用意する必要があるので Ubuntu 18.04 LTS の物理環境(USB通信の都合でVM不可)を作成して、NVIDIA sdkManager を入れておく。JetsonのOSイメージはホストOSのUbuntu 18.04とのファイルの合作で生成されるのでバージョンが大事。尚、Jetson Xavier NX 以降は最新のUbuntu にも対応している。
  • Jetson TX2 NX のオンボード eMMC (16GB) にはDeepStream を含めたすべてのファイルが収まらないので外部ストレージにOSを移動した後に、sdkManagerで追加コンポーネントをインストールすべき。

    dev.classmethod.jp

  • リモート管理系 (vino や dataplicity)等はTuring Pi 2 に移植する前にキャリアボード上で導入しておくと便利。

    zenn.dev

    www.dataplicity.com

Compute Module 4について

  • CM4の場合は背面NVMeに回路がつながっていないため使用できないが、ノード1とノード2の場合はMini PCIeが使用できる。
  • mPCIe から M.2 M-Key に変換する場合は次のようなアダプタが使用できる。

    https://www.amazon.co.jp/gp/product/B09LHMC36W/

    item.rakuten.co.jp

日本語化MOD用の Unity の asset の自動生成について

最近はテレワークの影響で仕事中の息抜き(散歩)ができず、かえって不健康になっている zan-gyo です。

 

Unity ベースのとあるゲームの日本語化を行っているのですが、現在進行形で新機能が実装されているゲームであるため 日本語化MOD に必要な .unity3d ファイルの頻繁な再生成が必要になっています。

翻訳自体は自宅サーバ上にある Zanata*1 という翻訳プラットフォームで行っているのですが、ゲーム内で翻訳内容を動作確認するには .unity3d の形式のファイルにパックしないといけません。

※ 私が関わっているゲームでは翻訳者向けにローカライズデータのみを差し替えられる仕組みが予め用意されていたので翻訳差分のみを .unity3d 化しています。

今回(?)はどうやれば .unity3d 形式でパックすることを自動化できるかの話です。

 

必要なもの:

- Unity 3D (エディタの機能のみを使うのでライセンスチェックは緩い模様?)

- パックするデータのフォルダ構造とメタデータ

- Tabletop-Simulator-Modding の TTSAssetBundlesMenuItems.cs ファイル。

github.com

 

↑の Tabletop-Simulator-Modding のファイル一式の中に Unity プロジェクトの Assets/Editor に展開する .cs ファイルがあるのですが、TTSAssetBundlesMenuItems.cs を所定の場所に設置すると Unity の Assets メニューに "Build AssetBundles" という項目が追加されます。

このメニュー項目を実行すると、.cs内のスクリプトによって Assets フォルダの中で出力対象に設定されているものがビルドされて、単体の .unity3d ファイルになります。

 

Build AssetBundles の自動化について

ビルド処理を自動化するにはコマンドラインから Unity 3D を起動して、メニュー項目を実行し、その後でプログラムを終了させる必要があります。

Jenkins (フリーのビルド管理ツール) に Invoke Unity3d Editor を追加している場合は以下のパラメタで実行可能です (Ubuntuで動作確認済み)。

-projectPath $WORKSPACE -batchmode -quit -nographics -executeMethod TTSAssetBundlesMenuItems.BuildAssetBundles
-projectPath $WORKSPACE

Jenkins が自動生成するビルド処理用の一時フォルダをプロジェクトファイルの所在地として指定

-batchmode 自動処理モードを指定
-quit 処理完了後にUnity3Dを自動終了
-nographics GUI を表示しない。
-executeMethod TTSAssetBundlesMenuItems.BuildAssetBundles メニュー項目を実行する

 

あとは:

  1. Unity3d が必要とするファイル一式を適当なソース管理システム (SVN / git) 等に登録して、Jenkins によって展開させる。
  2. 翻訳データを取得し、Assets フォルダ以下に展開する。
  3. 翻訳データの入っている親フォルダのメタデータで assetBundleName: を指定し、出力対象にする。
  4. Unity 3d で Assets のパッケージ化
  5. 生成されたファイルを配布用の場所へ移動

という流れになります。

#1 の Unity 3Dが必要とするファイル一式は使用する Unity3d のバージョンが上がったときだけに更新することになります(Unity 3dによってプロジェクトが自動アップグレードされますが、時間がかかるために予め外部で更新済みのプロジェクトを登録しておきます)。

 

 

 

*1:POEditのウェブ版のようなもので自前で設置する。 Javaベースで Docker Container を使うと展開が簡単だが MySQLバージョン依存のSQL文を使用しているためデータベースを最新にすると動かないことが多い。翻訳前データの取り込みに時間制限があるため1ファイルのデータ量が多い場合はシングルコア性能重視でCPUを選ばないといけない場合もある。1ファイル数万件の場合はAWS EC2ではスペックが足りない。

FuzeDrive SSD インストールメモ

FuzeDrive というのは Enmotus 社が出している階層化ストレージソフト。

ハードディスクとSSDをペアリングして高速化することができる。

キャッシュと違って階層化ストレージなので全容量が合算で使用できる。

もともとは Ryzen シリーズ用の StoreMI としてリリースされていたが、現在は単体で販売されている。尚、Ryzen用無料版 (SSD 128GBまで) は AMD のサイトでは配信停止されているが、Ryzen 用コストダウン版 が用意されている (FuzeDrive SSD にはハードウェアをライセンスとして認識する専用版がある)。

ww.enmotus.com

FuzeDrive SSD は Enmotus 社が出した階層化ストレージ構築用の SSD で、128GB SLC + 1.5TB QLC のハイブリッドとなっている。

実は QLC も TLCMLC も SLC もSSDとしての素子の数は同じで、違うのは保存できる電位の種別。

  1. SLC は 0 かそれ以外、
  2. MLCは 0 か 3状態
  3. TLC は 0 か 7状態
  4. QLC は 0 か 15状態

MLCTLCもQLCも安定して電位が保存できなくなったら素子としては死亡状態になるわけだけど、SLCに転用すれば延命できたりする。FuzeDrive SSDの場合は 元の容量が 2TB のQLC SSDで、512GB分のQLC素子をSLC運用することによって容量は4分の一に下がる (128 GB) が大幅なレスポンスの高速化と延命を可能にしている。

FuzeDrive SSDの有効化の手順だが、これは意外と落とし穴が多かった。

通常の手順は:

  1. インストール後に Windows Update 経由で Enmotus SSD ドライバを入れる。
  2. すると自動的に Microsoft Store からモニタリングツールが入り、SSD + QLC モードを初期化できる。
  3. 最後に Enmotus Fuzion X ツールをダウンロードして階層化ストレージを構成する。

ただし、 いくら Windows Update をしても最新版の Windows では Enmotus SSD ドライバが落ちてこないのである。

 

  1. Enmotus の SSD ドライバは以下から入手できる。

    www.enmotus.com

  2. Enmotus Fuzion モニタリングツールは以下から入手できる。

    www.microsoft.com

  3. Fuzion Xは以下から入手できる。

    www.enmotus.com

 

尚、 Enmotus SSD を使用する場合は FuzeRam メモリキャッシュは推奨されていないため Fuzion X には機能が含まれていない。 有料版の Fuzion XL を使用すれば FuzeRam も重ねることはできる。

 

 

MySQL で簡易 dhash 検索

dHash という画像検索用のアルゴリズムがある。

画像をグレースケール化して 9x8 のサイズにリサンプルし、隣合わせのピクセル同士を比較して増減に応じて 0 か 1 の値を設定して画像を 64bit 値にするというものだ。画像の検索には Binary Search Tree (2分探索木) を使って、3 bit 程度の誤差なら許容するような形で検索する。
※ グレースケール化やリサンプルのアルゴリズム、増減に応じて 0/1付与の方式によって dHash値の互換性が無くなるので長期の利用の際には互換性の維持については要注意である。

ただし Binary Search Tree を構築するのには時間と手間がかかるし、頻繁に検索するには Binary Search Tree のデータをメモリ上に長期間保持する必要があるので運用が面倒である。
そこで MySQL で Binary Search Tree を用いずに単純検索をしてみるとした場合、どうなるかを確認してみた。

MySQL には BIT(n) 型というのがあって、最大 64bit までの値を格納できる。今回はSIGNED/UNSIGNED関係にまったく気を配りたくないのでdhash値はBIT型にした。
※尚、UPDATE images SET dhash_bits = UNHEX(dhash); 等で16進文字列からBITへの変換は容易にできる。

一言でまとめると、MySQL には BITの立っている数を数える BIT_COUNT() 関数があるので単純に dhash同士でBITWISE XORしたものの立ちBIT数を数えれば良いようだ。

SELECT HEX(dhash_bits), BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') AS SCORE
FROM images
WHERE dhash_bits IS NOT NULL
  AND BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') <= 3
ORDER BY BIT_COUNT(dhash_bits ^ b'1111000111110000111000100100000001100100010011001101001011111001') ASC

※ 当然だが Binary Search Treeでは無いので大容量検索の場合は効率が悪くなる。

UNRAIDを試してみた

Linus Tech Tips (https://www.youtube.com/user/LinusTechTips/) でも紹介されていた UNRAID を試してみた。 

unraid.net

 

UNRAIDはよくある FreeBSD 型のソフトウェアRAIDNASアプリアンスだが、従来のものとは異なる独自路線を貫いている。

一言で言うと、「一日のデータ処理量はHDD一個に収まるぐらいだが、総データ量はバックアップが億劫になるぐらい大量にあって、且つデータロスは最低限に抑えたい」というニッチなものだ。

製品はUSBメモリにファイルを展開する方式で、30日間の機能無制限体験版 (要インターネット接続)が付いてくる。トライアル期間後は要ライセンス購入。

UNRAIDは RAID3 や RAID4 のようなパリティドライブ固定式のソフトウェアRAID方式だが「データをストライプしない」という特徴がある。

RAIDにおいてパリティのデータは他のドライブ上の情報を XOR 演算する等で求められるが、パリティ計算だけについて考えれば各ドライブ内のファイルシステムはまったく関係が無いわけだ。

極端なことを言うと 4台HDD構成で HDD1 を NTFS、HDD2 を exFAT、HDD3 を ext4 にしてもパリティは問題なく計算ができ (実際にUNRAIDがサポートするのは xfs, btrfs, reiserfs)、HDDロスト時にも残存ドライブの情報を元に欠損したHDDの情報を逆算できる。

RAIDの場合はデータをストライプすることによってパフォーマンス向上を狙うが、パリティドライブ数+1のHDD欠損で全データをロストする。UNRAIDでは各データドライブは通常のファイルシステムのまま運用されるので、複数のHDDが欠損しても残存HDD上のデータは専用の復旧ソフトの必要もなしに復元できる。必要なのは対象ファイルシステムに対応したLinux の Live Boot メディアだけだ。

尚、従来のRAID5/6ではパフォーマンス高速化のために以下のような最適化がとられているが UNRAIDはこれらの最適化を悉く外してきている。

従来のRAID5の最適化:

  • データストライプによる複数HDDの同時利用によるパフォーマンス高速化
    → ただしデータロストの危険性あり
  • パリティドライブ非固定によるHDD消耗の均等化
    → ただしHDD複数台同時故障の危険性あり
  • 一斉書き込みによる書き込み操作の単純化

 UNRAIDでの状態:

  • データをストライプしないので複数HDD同時欠損でも完全データロストしない(ただし1デバイス分の帯域しか使えないので転送速度が遅い)
    → 全ドライブ同時書込みをしないのでHDDの回転モーター同調の問題が発生しにくく、NASグレードのHDDを必ずとも必要としない(私見
  • パリティドライブが固定なのでパリティドライブが消耗しやすく、故障の予測が立てやすい
  • パリティ書込み時に他のドライブの内容を読み取ってからパリティ計算するので処理に二手間かかって遅い

UNRAID の問題だが、RAIDのパフォーマンス最適化を悉く外してきているためとんでもなく書き込み処理が遅いこと(特にパリティ計算による2重レイテンシーが致命的)だ。

そこでUNRAIDのパフォーマンスに関わってくるのがキャッシュドライブという名のワークエリアだ。キャッシュドライブはxfs / btrfs (2台でRAID1をする場合は btrfsのみ)でフォーマットされた作業エリアで、通常UNRAIDはキャッシュドライブに変更分のデータを書き込み、夜間にまとめてUNRAIDアレイに反映するという方式をとる。言ってみれば ソフトウェアRAID1から自動バックアップできる高可読性ソフトウェアRAID5/6がセットになっているわけだ。

一日の作業量がキャッシュドライブの容量に収まるのであれば読み書きは極めて速い。10GBe 等にも対応しているので適切に構築されたUNRAIDサーバであれば動画編集にもまったく問題なく対応ができるレベルだ。

UNRAIDでは分散構造のファイル階層を採用しており、キャッシュドライブと各HDDの中を横断したファイル階層をもっている。もし HDD1 に /share/backup/file1.txt というファイルがあり、HDD2 に /share/backup/file2.txt というファイルがある場合、外から見ると一つのフォルダに双方のファイルがあるように見える。

各HDDにファイルが書き込まれる時にはネットワーク共有毎に設定できる三つの分散アルゴリズムのうちの一つが使用される。

  • High-Water: 水槽から溢れた水が隣の水槽に注ぎ込むイメージ。HDD1を50%まで使い、HDD2を50%まで使い、全部50%まで貯めたらHDD1を75%まで貯める、という方式
  • Most-Free: 空き領域が一番多いHDDに配置
  • Fill-up: HDD1から順番に配置し、一杯になったら次のHDDに移動

UNRAIDアレイ上のフォルダ構造の分割はファイルの書き込み毎に行われるが、一度ファイルの書き込みが始まると対象HDDは固定になる。最初に0バイトファイルを作成した後でファイルを拡張し、対象HDDの空き領域を超えるデータ書き込みを行うと「容量不足エラー」になるのだ。同じファイルを2度目に書き込むと別HDDに配置されるので問題回避できるが同様の問題はキャッシュドライブ側でも発生する(キャッシュドライブの容量を超過する書き込みは自動的にUNRAIDアレイに直書きになる)。サーバ間引っ越しでデータを大量に書き込んでキャッシュドライブ容量を超過すると一時的に容量不足エラーで爆死する(再実行で直る)。

※ キャッシュドライブの容量内で運用している場合はUNRAIDアレイに変更を反映する時点でファイルサイズが固定化しているためこの問題は発生しない。

 

尚、UNRAID は FreeBSD系のNASソフトウェアであり、当然のように同系統のSMBの制限によって制約される。ファイル名 255バイト制限だ。

UNRAID の対応ファイルシステムは xfs (最大ファイル名 255バイト)、btrfs (255バイト), reiserfs (4Kバイト) と長いファイル名に対応している reiserfs にも対応しているが、これは以前のバージョンとの下位互換性のために用意されているだけで reiserfs を使うことによってファイル名長の制限を回避することはできない(推奨は xfs)。

という感じで通常のNASユーザーには使いづらいことだらけだが、PBクラスのストレージ容量を扱って 且つRAID破損によるデータロストを避けたいのでれば十分に検討しても良いものだ。ライセンス価格は接続HDD数ごとに分かれているが、大量HDDでも価格は安い。

unraid.net

 

ネットワーク回りではUNRAID は FreeBSDと同様に マルチギガ (10GBe+) 等に対応しており、複数NICの場合は bonding モード (複数NICのロードバランス)とbridge モード (子ネットワークノードからの通信が親ノードに流れる)に対応しており、NASに接続した 10GBe 側から通常の Gigabit ネットワークに通信を流すような運用も可能だ (DHCPが通過するかは未確認)。

また、Dockerや仮想マシンの実行機能も備えており、夜間処理用にハイパフォーマンスCPUを備えても、処理能力は無駄にはならない(コミュニティアプリストアからパッケージの導入も可能)。

尚、筆者は低消費電力CPUのオンボードSATAで手軽にホームNAS、と考えて Athlon 3000G (2C4T、35W TDP) でシステム構築したがUNRAIDアレイ直書き時のスループットが 40MB/秒で最初のサーバ間コピーが長すぎて泣く泣く 2720A SGL を購入して Windows Server運用に切り替えた。