今後2週間の研究進捗(すべき)内容
とにかく最低限の物を作る。
普通のSMP+TBBのコードでは
fib(int n) { // 再帰の端を果てしなく略 task_group tg; int x=0; tg.run([=,&x]{ x += fib(n-1); } const int y = fib(n-2); tg.wait(); return x + y; }
とかできるそうだ。C++11のstd::asyncとかもあるけど先生はそういうのが嫌いなようだ。
実際にはそうでないものをあたかもそうであるかのように見せかけるのは嫌いだ。
とても哲学的な意見であり、俺には肯定も否定もできない。ただ、見かけ上うまく行ってもデバッグがすごく難しく、ソースを読んで初めて実装がこんなことしてたのか!と気づくようなものは厄介だというのは確かに同意できる話だ。それはともかく俺はC++が好きだ。
閑話休題、これをまずは分散メモリ上で「遅かろうが何だろうが」validに動作させるのが当座の目標というわけだ。もちろんM2の先輩のコードを利用して。そのためには共有変数xをイカサマする必要がある。分散ノード上でタスク並列という事はいつワークスチールされるかもわからず、つまりはちゃんとしないと大変なことになるわけだ。おそらくそのためにポインタをポインタとして出すインターフェースと、それの参照のようなものがあると便利だろう。
template <typename ValueType> class dist_ptr { distptr_t ptr; public: dist_ptr(); dist_ptr(ValueType * ptr); //<! なんかマズイ気がする // ...略...new/deleteのオーバーロードがしんどいんじゃね? }; //! 分散配列、こっちのほうが楽 template <typename ValueType, size_t N> class dist_array; template <typename ValueType> class dist_vector; template <typename ValueType> class dist_ref { dist_array<ValueType, 1> ref; public: //! コンストラクタ、implicitでいいんじゃね? dist_ref(ValueType val) { ref[0] = val; } // デストラクタはいらない. //! not copy constructive. dist_ref(dist_ref<ValueType> &) = delete; //! but move constructive dist_ref(dist_ref<ValueType> &&) = default; // ...以下略...代入演算子とValueTypeへのimplicitなキャスト演算子の定義だろうか? };
unique_ptr, shared_ptrの特殊化とか、STLのアロケータ指定で解決できるのならばそれもよしだが…カスタムアロケータとか使ったことないや。