トップ

数値計算フレームワーク「ポコム」(新形式)

2023/8/12以降 gcc/g++ で直接コンパイルするには -I. オプションが必要です。

プログラマーズ ガイド http://isaku-wada.my.coocan.jp/pocom/pocom.html

ダウンロード(Windows) (S-JIS) http://isaku-wada.my.coocan.jp/pocom/pocom.iso

ダウンロード(Ubuntu) (UTF8) http://isaku-wada.my.coocan.jp/pocom/pocom-utf8.tgz

ダウンロード(Other Linux) (EUC-jp) http://isaku-wada.my.coocan.jp/pocom/pocom-euc.tgz

pocom.iso をダウンロードした場合は、それをダブルクリックしてマウントし、 出現した pocom.zip を適当なフォルダにドラッグしてコピーします。 その後、マイコンピュータ(PC)を開き、【DVD ドライブ(?:) POCOM】を右クリックして 【取り出し(J)】を実行して アンマウントします。('?:'は環境によって'D:'や'E:'や'F:'のように変わります。 マイコンピュータ(PC)に【DVD ドライブ(?:) POCOM】が表示されない場合は、 [F5]キーを押すか、右クリックして【最新の情報に更新(E)】実行してください。)

コピーした pocom.zip を右クリックして 【全て展開(T)...】を実行し【展開(E)】をクリックします。新しく作成された pocom という フォルダを開いて $DoFirst.bat ファイルを実行します。

ポコムとは

ポコム(POrtable COMpiler)はC/C++を使った、小型のフレームワークです。 ポコムはフリーソフトウェアです。無料で使うことができます。 ポコムは数値計算、なかでも待ち行列網、グラフ理論や統計分析に向いています。 ポコムは軽くて速いプログラムを、手っ取り早く開発するのに向いています。 ポコムを使う効果はつぎのとおりです。

背景

現在、数値計算のプログラムを組む時に選べる言語はたくさんあります。

パソコンならエクセルのマクロを使うと便利です。 エクセルなら400種類以上のVBA関数やワークシート関数が使えます。 また、エクセルの他の機能と組み合わせて、 少ない手間でかなり高度なアプリケーションを作ることができます。 必要ならWinAPIビューアでOSレベルの操作も可能です。 また、広く普及しているので多くの人に使ってもらえるのも強みです。

他にも、フリーソフトのawk,perl,Ruby等の、 スクリプト言語を使うと便利な場合があります。 これらには、正規表現による検索等、 あらかじめ使える機能が豊富に用意されています。 また、柔軟なデータ構造を持っています。 これら言語は、数値計算の分野でも、 プロトタイプなどでよく使われます。

現在のこうした状況で、 C/C++で数値計算プログラムを作る意義は次の通りです。

(意義1) C/C++は高速である
スーパーコンピュータにおけるFORTRANを除けば、 C/C++よりも速い言語はアセンブラ位しかありません。 問題の種類によりますが、エクセルのマクロの 20 倍位速くなります。 また、awkの、80 倍位速くなります。 C++の素晴らしい点は、Cよりも言語仕様が複雑になったにもかかわらず、 処理速度が全く遅くならないことです。 一方、JavaやC#は中間コードを生成したり、 エラーチェックを計算時にも行うため遅くなりました。 また、C/C++は SSE2 や OpenCL など、ハードウェアの性能を引き出すこともできます。
(意義2) C/C++は広く普及している
大抵のプラットホームにCコンパイラは用意されています。 本も無数に出版されているので、使える人が大勢います。 過去に蓄積したノウハウやライブラリを使うことができます。 コンパイラや開発環境も、多くの使いやすい製品があります。

C/C++はメモリ管理とデータの入出力は単純な仕様になっています。 これが、C/C++の柔軟性を高めるという長所であると同時に、 自分で低レベルなプログラムを書かなければならないという欠点でもあります。 そのため、Cは高級言語と呼ばれません。

そこで、プログラムごとに入出力を書かずに済ますために、 共通のプログラムを作ることにしました。 これが ポコムです。

RMATを使った転置行列を作る例

ポコムによる数値計算プログラムがどのようになるか、 転置行列を作るプログラム例 Tra.c を説明します。
#define FILE_NAME "Tra.c"

#if defined(PDEF_H)

 INT(N,3,          EJ("Size of matrix",  "行列の大きさ"              ))
 RMAT(SrcM,307,N,N,EJ("Input matrix",    "入力となる行列"            ))
 RMAT(DstM,307,N,N,EJ("Output matrix",   "転置した結果を記録する行列"))
 PROC(Transpose,   EJ("Transpose matrix","転置行列を作る計算ルーチン"))

#else

 #include "../pocom.h"
 CHECK_FILE_NAME

 void Transpose(void) {
     Int i,j;
     Check("SrcM"); Alloc("DstM");
     for (i=0;i<N;i++) for (j=0;j<N;j++) DstM[j][i]=SrcM[i][j];
 }

#endif

とします。 (3と307は、表示桁数を決めています。 3は3桁、307は7桁・小数点以下3桁を意味します。 詳しくはドキュメントを参照してください。)

ここで、入力ファイルと出力の例を以下に示します。

 SrcM
   2   5   7 ;
   4  13  20 ;
   8  29  50 ;

 Transpose
 Print N SrcM DstM

';' は行の終わり、空白行は配列の終わりを意味します。 入力ファイルの行列 SrcM を読み込むと、変数Nは自動的に3になります。 入力ファイルの Transpose を読み込むと計算が実行されます。 そして、Print N SrcM DstM 文が出力する内容は以下のようになります。

 N   SrcM                      DstM     
   3   2.000   5.000   7.000 ;   2.000   4.000   8.000 ;
       4.000  13.000  20.000 ;   5.000  13.000  29.000 ;
       8.000  29.000  50.000 ;   7.000  20.000  50.000 ;

ポコムの目標

まず、「数値計算のプログラムを開発する」とは、 「論文・教科書等の文献で説明されているデータ構造やアルゴリズムをC/C++で記述こと」 と考えました。 そして、次のような目標を立てました。

RMAT マクロを上の例のように宣言すると、ポコム内部では、 ポインタ変数 double**SrcM; と、制御構造体 rmat_ SrcM_[1]; が確保されます。 制御構造体は、入出力とメモリの管理を行うときに、利用されます。 そして、必要に応じて、ポインタ変数 SrcM を設定します。 C/C++プログラム上での変数名と、データファイル上での変数名は一致します。

制御構造体を使った動作は、巧みに隠されていて、計算ルーチンを書く場合でも、 意識する必要はありません。 計算ルーチンでは、ポインタ変数 SrcM のみを使って、配列の各要素にアクセスします。 プログラミングの面倒な部分は pocom.h に任せて、 計算ルーチンはシンプルに書くことができます。

また、OSやコンパイラに依存しないプログラムを簡単に書くことができます。 さらに、文字コードも、Shift-JIS、EUC-jp、UTF-8 に対応しています。 日本語を使っていても、ソースファイルとデータファイルを nkf などで変換するだけで、 プログラムを編集せずに、簡単に他の文字コードに移ることができます。 ポコムは、メモリを動的に確保して、無駄なメモリを使わないことに力を注いでいます。 その結果、16ビットコンパイラで動くプログラムのソースコードを、 全く変更せずに、64ビットでコンパイルして大規模データにも対応できます。

これにより(目標1)が実現できました。

今時、64Kbyteの制限を気にしてプログラミングするのは、 時代遅れだと思うかもしれません。 4Gbyte以上のメモリを積むのがあたりまえの世の中、静的に大きい配列を 確保しておいたほうが、プログラムが簡単になって良いという考えです。

でも、使用メモリを可能な限り小さくするのは、今でも重要なのです。 使用メモリが小さければ、CPU内臓のキャッシュメモリに全体が納まり、 飛躍的に高速になる可能性があるからです。

また、計算で変数を読み書きする時に添え字の範囲チェックや、文字列処理、 関数呼び出し等は行われません。 これにより(目標2)が実現できました。

古いMS−DOSでは、暴走するとシステムを再起動しなければならないだけではなく、 フロッピー・ディスクを破壊する可能性もありました。 UNIXやWindowsでは暴走しても再起動する必要はありませんが、 暴走の原因が分かりにくくなるので、 避けるべきであることには変わりありません。 (目標3)は、このような背景から掲げられました。 ポコムでデータを読みこみ、計算ルーチンで Check( ) を使って検査すると、 暴走せずに、適切なエラーメッセージを表示して、 安全に終了するプログラムを作成できます。

つまり、チェックは読み込みの段階で厳しく行なって、 計算するときはスピードを優先するという方針です。