Rustで構造解析プログラムをつくってみたときの備忘録

8412 ワード

はじめてのRust

表題のとおり、初めてRustで本格的にプログラムを書きました。
いろいろ悩みつつ一応まともに動いたのでまとめとして記事を書きます。
記事として書いていますが、備忘録的な側面が強いため、あまり誰にでもわかりやすくは書いていないです。ご了承ください。

なお、環境はWindowsです。

なぜRustか

これまで主にC#,F#でプログラムを書いてきましたが、やはり実務で利用するには計算速度の面で商用プログラムよりも性能が劣ると感じていました。
ただ、C,C++などの低レベルのプログラミング言語は苦手意識があったため手を出しづらかったところがあります。
そこで、最近パフォーマンス面と言語機能で注目を集めているRustを試してみることにしました。

難しかったところ

難しかったところをまとめます。
※初めてのRustかつ低級言語に慣れてないなので非常に初歩的な内容で詰まっていると思います。

なにはなくとも、借用が難しい

Rust大きな特徴である、借用の概念が難しかったです。
最初はなぜエラーが出るのかわからなかったですし、正直いまでもよくわからないときがあります。

ただ、ありがたいのは、Rustのエラーメッセージが親切であることです。
エラーメッセージで、「ここは借用にしないといけないよ」と教えてくれるので、その指示に従ってコードを修正していけばうまくいくようになってきます。
本当は、そのあたりの挙動の理解してコードを構成していくべきですが、エラーに従って直していけば一応ゴールにたどり着けるというのは学習するうえでは挫折しにくい理由になったのかなと思いました。

↓こんな感じで、どこで借用されてしまっているかちゃんと教えてくれます。

配列の使い方

Rustでは配列は、コンパイル時にサイズが確定している必要があります。
今回作ったプログラムは、実行時に計算対象のサイズを確定するため、C#で実装するときは double[] values; のような形で型宣言だけおこない、実行時に values = new double[size]; のような形で使っていました。
Rustではこのような記述ができません。
サイズが実行時に確定する場合にはVecを使うということになっていますが、Vecは実行時にサイズが確定できる反面、インデックスアクセスは配列に比べると遅いことがベンチマークの結果としてわかりました(予想通りですが)。
大きめの固定長の配列を用意することも考えましたが、やはりもやもやしたのでもう少し調べてみたところBoxを使う方法があることがわかりました。
これを使えば、実行時にサイズを確定しつつ、インデックスアクセスも配列なみに高速でした。いちいち記述が冗長になりますが、目的は果たせそうなのでよしとしました。
もっといい方法もありそうな気がするので、詳しい方教えていただけると嬉しいです。

let mut values = vec![ 0; size ].into_boxed_slice();
let x = values[0];
values[1] = 100.0;

疎行列計算

対象とする問題の最も計算負荷大きいところが疎行列の計算だったのですが、うまく既存のCrateが使いこなせませんでした。以下を試しましたが、ドキュメントを見てもうまく扱えませんでした。主に自分のスキル不足が原因であり、それぞれのCrateについて評価できるほど調べ切れていないです。
ですので、本当はやりたい機能を持っていたのかもしれませんが、使いこなせませんでした。

sprs