GNU OctaveのTips

データをファイルに書き出す際の注意点

Matlabやその互換の数値計算ソフトであるOctaveは,変数が基本的に配列であるという長所を持ちます. そのため,行列やベクトルを扱うときはCやFortranに比べると,計算時間はそれほど変わらないにも関わらず,プログラムが簡潔になります. その反面,配列の要素を順番にアクセスする時にforループを使うと速度が落ちるので,Octaveのプログラムを書く際にはなるべくforループを使わないというのが鉄則です.

Octave自体が様々なグラフを描くことができるので,Octaveの中で計算から結果の表示まで完結できます. しかし,様々な事情により他のソフトにデータを渡す必要が生じることもあります.

このような場合には,Octaveでのデータをファイルに書き出す必要があります. 例えば,N要素の列ベクトル x, y, z を出力する際には,以下のようなfor文でfprintfのループを書きたくなります.

      for idx = 1 : N
        fprintf(fid, "%e %e %e\n", x(idx), y(idx), z(idx));
      endfor
    

しかし,この場合にもOctaveではfor文は遅いというルールが適用されます. そのため,データを大量に記述する時には一時的なデータ配列を作ってfor文を使わないようにしなければなりませんが,Octaveの配列のメモリへの格納形式は以下のようなFortran形式の列優先の形式であることに注意しなければなりません.

      A(1,1), A(2,1), A(3,1), ..., A(1,2), A(2,2), ...
    

一方,ファイルに書くときは1行ごとに出力するため,行優先のC形式の配列である必要があります.

以上より,for文を使わないでN要素の列ベクトル x, y, z を出力するには,ファイルに書きたい形で一時的な配列を作って,その転置をfprintfの引数に指定することにより以下の文となります.

      fprintf(fid, "%e %e %e\n", [x, y, z]');
    

データ数が少なければ両者の差はそれほどではないと思います. しかし,筆者が100×10,000のデータ配列の各要素を1行ずつ書き出して1,000,000行のデータファイルを出力するプログラムを作ったときには,forループでは1分ぐらい実行時間がかかったのが,配列で出力するようにプログラムを変更しただけで実行時間が数秒となるという効果がありました.

作業中のディレクトリ以外にある関数ファイルを編集する時の注意点

デバッグなどのためOctaveを操作しながら,関数ファイルの編集をすることはよくあることと思います. その際に注意しなければならないこととして,自分で追加したパスなどで作業中のディレクトリ(カレント・ワーキング・ディレクトリ)以外に関数ファイルがある場合はファイルを更新していても,次に実行する時はメモリ上の関数を実行してしまうということがあります. そのため,例えば"my_function.m"の関数ファイルを更新した場合はその都度,以下によりOctaveのメモリ上の関数をクリアする必要があります.

      clear my_function
    

なお,関数ファイルがカレント・ワーキング・ディレクトリにある場合は,Octaveが関数ファイルの更新時間をチェックしてメモリ上の関数よりファイルが新しければファイルを読み直しますので,問題はありません.

筆者は環境変数OCTAVE_PATHで設定したディレクトリに関数ファイルを置いて別のディレクトリで作業しているので,以前は関数ファイルを更新したらいつもクリアが必要と勘違いしておりましたが,マニュアルを読んでみると上記の通りでしたので,記述を修正しました.

Windows版Octaveにおけるフォント

Windows版Octaveに付属するショートカットでは英語環境に設定されているため,dirなどの日本語を出力するコマンドでは日本語が文字化けします. そのため,Octaveのショートカットのプロパティにおいて,「オプション」の【現在のコードページ」を日本語Shift-JISに変更し,「フォント」をMSゴシックに変更して,適用ボタンによりショートカットを更新しておくと良いでしょう.

Last update: 2012.12.13

[機械力学研究室ホームページに戻る]   [数値計算に関する情報のページに戻る]