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 (GUI) ではメニューなどが日本語で表示されるにも関わらず,コマンドの実行の画面は日本語に対応していません. これは,コマンドラインインターフェースの CLI でも同じです. そのため,Octave の m ファイルで日本語で表示させると文字化けします. なお,エディタに関してはデフォルトでは Shift_JIS が表示できますので,コメントだけは日本語で書くことができます. ユニコードの場合は Octave の編集メニューで「設定」を選び,エディタのタブでテキストのエンコードを UTF-8 に変えることによって表示できます. ただし,この設定のウィンドウのエディタのタブでテキストのエンコードはかなり下にありますので,スクロールしなければ見えません.

エディタの設定でエンコードにUTF-8を選ぶ

GNU Octave(GUI) を Windows で実行したときに,同時に GNU Octave(CLI) も立ち上がる問題について

このページで議論されているように,現在の Octave は Windows 11 でデフォルトのターミナルとなっている Windows ターミナルをうまく扱うことができないため,Octave(GUI) を実行すると同時に Octave(CLi) も立ち上がります. この二つの Octave は入出力を共有しているので CLI の黒い画面を最小化すれば良いのですが,Octave(GUI)を実行する度に最小化するのが面倒な場合には,Windows のメニューの「設定」→「プライバシーとセキュリティ」の中,あるいは「設定」→「システム」の中の「開発者向け」→「ターミナル」を従来の "Windows コンソール ホスト" に変更すれば,CLI のウィンドウが出なくなります. これは,Windows ターミナルをインストールした Windows 10 も同様です.

Apple Silicon Mac に Homebrew でインストールした Octave へのパッケージのインストール

Linux 版の Octave では各種パッケージのバイナリが提供されており,Windows 版の Octave ではインストーラに各種パッケージが含まれていますが,Homebrew の Octave では必要なパッケージを自分でインストールする必要があります. ここで注意しなければならないのは,Homebrew で提供される Octave では追加するパッケージを clang でコンパイルしなければならないという点です. そのため,以下の例であげる gsl や parallel などのような Homebrew で提供されるライブラリを必要とするパッケージは,コンパイル時にヘッダファイルとライブラリの場所を指定する必要があります. ただし,環境変数として CPPFLAGS や LDFLAGS を用いると,octave の中でコンパイルするコマンドである mkoctfile で設定されている値を上書きしてしまいますので,clang の環境変数 CPATH, LIBRARY_PATH を使用します.

例えば,gsl パッケージをインストールする場合には,gsl 2.1.1 ではマクロが正しく定義されないエラーが出るので,ターミナルで以下を実行してインストールします.

      $ brew install gsl
      $ export CPPFLAGS="$(octave --eval 'mkoctfile -p CPPFLAGS') -DOCTAVE_HAS_OV_ISREAL_METHOD -DOCTAVE_HAS_FEVAL_IN_OCTAVE_NAMESPACE"
      $ env CPATH='/opt/homebrew/include' LIBRARY_PATH='/opt/homebrew/lib' octave --eval 'pkg install -forge gsl'
    

parallel パッケージをインストールする場合には,ターミナルで以下を実行します.

      $ brew install gnutls
      $ octave --eval='pkg install -forge struct'
      $ env CPATH='/opt/homebrew/include' LIBRARY_PATH='/opt/homebrew/lib' octave --eval 'pkg install -forge parallel'
    

Last update: 2024.1.18

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