Imaginantia

思ったことを書きます

メモ250511 データ表現のこと

最近は相対的に広い話題のことばかり考えてましたがたまには狭いことを考えようと思ったので書きます。向こうに書いても良かったけどまぁこっちが不変なのもアレなのでこっちにしました。

SoA と AoS ってあります。私はいつもどっちがどっちかわからなくなりますが。

Structure of Arrays は、各要素がそれぞれ配列になってるやつ。

struct Vertices {
  Vector3 pos[N];
  Vector3 normal[N];
  Vector3 color[N];
};
Vertices vertices;

Array of Structures は、要素からなる構造体の配列。

struct Vertex {
  Vector3 pos;
  Vector3 normal;
  Vector3 color;
};
Vertex vertices[N];

まずこの2つは equivalent (お互いに情報を失わず変換可能) です。全く同じ情報量を持ちます。

しかし、データの持ち方が違うので使い方・使われ方に差が出ます。

  • 各要素毎の処理をする場合は、AoS のほうが「正しく」書ける
    • 1要素のことを考えているときにわざわざ pos[i] みたいに index が絡んでこない
  • 全posに対して処理する、みたいなときは SoA の方が「正しく」書ける
    • pos のことを考えているときにわざわざ v.pos みたいに他の要素が絡んでこない

このように「使う」レベルの時点で最適性は明らかではないわけですが、「使われる」ときの最適性はもっと明らかではありません。並列処理だと典型的には SoA のほうが速いみたいです (連続 index に対するデータアクセスが連続する?)。

が、メインの処理を書くときにその辺のことは考えたくないです。もっと言うと考えるべきではありません。それは違うレイヤーの話です。つまり:

  • AoS か SoA かは自由に切り替え可能であってほしい
  • 切り替えてもコードはできる限り不変であってほしい

という気持ちがあります。行列を row-major か column-major かとかも似たような話ですね。

つまり、「実行時最適だからこれを選択する」のではなく、「どちらでもいいけど、試してみたらこっちのほうが速いからこれを選択する」であるべきだと思うのです。それが「知識を表現する*1」ということだと思います。

で。

それをどうやるか、と考えたときに… C 言語とかは (元々レイヤーが低いので) フォーカス外ですが、まぁ例えばインタフェースで云々みたいなことが考えられるとは思うんです。

が、多分それも間違っていて。アレはもっと「違うもの」に共通の受け口を付ける話なので、「同じもの」のことを扱うのには向かないような気がします。具体的に言うと indirect call は「違う」から必要なのであって、ここまで同じものをわざわざ dynamic に呼んでいては勿体ありません。

じゃあマクロがいいのかというとマクロ自体が論外なのでやりたくありません。でも筋としては近くて (マクロは実行時に何も影響を与えないから)、結局ほしいのは「言語機能」というよりも「内部構造を表に出す機構」なのだと思います。これは典型的には「コンパイラがいい感じにやってくれる」ということで隠蔽されるものでありましたが (まぁ足りないので repr(C) とか出てくる)、やはりこれが何らかの形で見えるべきなのではないかと思うのです。

ちなみに面白い言語があって。github.com

誰かさんの自作言語なんですけど、struct SOA 指定すると配列が SoA で並ぶらしいです。その上で通常通りの要素操作構文が使えます。こうあるべきなのです。というかこれくらいなら単純な部類だと思います。

…えー、ちょっと雑多に書いているのでわかりにくい感じになってますが:

  • まず表現形式が違うことが構文に漏れ出るのは嫌
  • マクロで隠蔽は辛うじてできるかもしれないけどキモいので嫌
  • interface つけるのは勿体ないので嫌
  • Jai は面白いな~

という気持ちです。

 

「面白いな~」というのは面白いな~というくらいで。結局内部表現が完全にコントロールできるわけではなくて… SoA / AoS 論争 (?) くらいにしか使えません (当然)。 実際、内部表現はなんだかんだコントロールしたいことが多いような気がします。正確には、完全コントロールする方法と、それを自動化する方法がほしい気がします。

とは言え内部表現としては何でもあり得るわけで、並び順だけとかそういうものでもない…ので… なんかこう。univalence あたりがいい感じにやってくれないかなって思ってる。知らんけど。

それを言ってしまうと話が終わってしまうんですが。

これまでの言語が「勝手にいい感じにしてくれる」のは「内部表現は気にしないだろう」もしくは「適切な内部表現は定まっているだろう」という過信から来ていて (正確には「環境によって可能な表現が違うことがあるから柔軟にしておかないとマズい」から)、「適切な内部表現」が定まらないという事実がある以上、それは外に出てほしいなと思う (環境によってコンパイルエラーになっても別にいいと思う)。

いい感じになってほしいですね。

*1:こっちが速いという暗黙知識のままではなく、2つが等価であることと、その上で片方を陽に選択したことをコード表現として記す