2008-02-29

GSL ライブラリを利用したコンパイル

SourceForge.net Logo
GSL (GNU Scientific Library) は、科学技術計算用 C ライブラリです。このライブラリは C 用にスクラッチから(一から)書き起こされ、API (Application Programming Interface)の形式でライブラリの各関数を利用できるようになっています。GSL のソースコードは GPL に従って配布されます。

今回は、MinGW クロスコンパイル用に公開している GSL ライブラリを使ったコンパイル例の紹介と、注意点(問題点)に関するメモです。今回使用するサンプルは、以下の通り。


/******************************************************************************
* grand.c
* GNU Scientific Library (GSL) 用サンプルプログラム
*
* 分布関数に従う乱数
*
* ヘッダーファイル(GSL)
* - Random Number Distributions(乱数分布)用
* gsl/gsl_randist.h
*
* 使用する主要関数
* double gsl_ran_gaussian (const gsl_rng * r, double sigma)
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_statistics.h>

#define DATA_NUM 10000

int
main (void)
{
int i, n = DATA_NUM;
double sigma = 1.0, data[DATA_NUM];
gsl_rng *r;

/* 乱数生成のためのインスタンス(ジェネレータ)生成 */
r = gsl_rng_alloc (gsl_rng_default);

/* システムクロックを使って乱数の初期値を設定 */
gsl_rng_set (r, time (NULL));

for (i = 0; i < n; i++)
{
/* ガウス分布(正規分布)に従う平均 0、標準偏差 sigma の乱数 */
data[i] = gsl_ran_gaussian (r, sigma);

if (i % 10 == 0)
printf ("\n");
printf ("%7.3f", data[i]);
}

/* 検証用の統計値出力 */
printf ("\n\nRandom Numbers in Normal Distribution, N(%.2f, %.2f)\n",
0.0, sigma);
printf ("Size : %d, ", n);
printf ("Mean : %8.5f, ", gsl_stats_mean (data, 1, n));
printf ("STD : %8.5f\n", gsl_stats_sd (data, 1, n));

return EXIT_SUCCESS;
}
/* grand.c */

これを Linux 上でクロスコンパイルすると、なにやら警告メッセージが出てきます。

$ i386-mingw32-gcc -Wall grand.c -lgsl -lgslcblas -o grand.exe
Info: resolving _gsl_rng_default by linking to __imp__gsl_rng_default (
auto-import)
/usr/local/lib/gcc/i386-mingw32/4.2.1-sjlj/../../../../i386-mingw32/bi
n/ld: warning: auto-importing has been activated without --enable-auto-
import specified on the command line.
This should work unless it involves constant data structures referencin
g symbols from auto-imported DLLs.

grand.exe はコンパイルされ、ちゃんと実行できますが、毎回こんなメッセージが出るのは煩わしいことです。このメッセージは、--enable-auto-import オプションをリンク時に指定せよということなので、コンパイル時にオプションを指定してコンパイルしてみます。

$ i386-mingw32-gcc -Wall grand.c -lgsl -lgslcblas -o grand.exe -Wl,--en
able-auto-import

$

たしかに、警告メッセージが出なくなります。しかし、このオプションって、MinGW のリンカではデフォルトで有効になっていたような…。リンカの問題なのか GSL のビルドに問題があるのか調べる必要がありそうです。

ちなみに、このプログラムの WINE 環境での実行結果は次のようになります。

$ pwd
/home/bitwalk/work/gsl
$ cd /usr/local/i386-mingw32/bin
$ /home/bitwalk/work/gsl/grand.exe

-0.389 -0.794 -1.418 0.717 1.348 -0.249 -1.727 0.153 -0.510 0.212
0.122 -1.673 0.060 0.162 0.509 0.303 0.883 -1.841 -1.260 0.515
1.595 0.109 0.869 -0.099 -0.055 1.756 -0.480 -0.431 0.389 1.816

(途中省略)

1.161 -0.384 1.051 -0.341 -1.550 -0.194 1.344 -1.377 -1.127 -1.453
1.458 0.081 0.443 0.137 -0.177 0.641 0.329 -0.501 0.352 -1.382

Random Numbers in Normal Distribution, N(0.00, 1.00)
Size : 10000, Mean : -0.00621, STD : 0.99311
$

MinGW クロスコンパイル環境でコンパイルしたライブラリも増えてきたので、そろそろ DLL だけを集めたランタイムパッケージを用意した方が便利そうです。

スタティックライブラリの利用


Windows 上にビルドしたバイナリを移して実行する際、必要な DLL も同じディレクトリに持ってくるのが面倒な場合、スタティックライブラリを利用する方法もあります。通常のコンパイルで、共有ライブラリ (DLL) とスタティックライブラリの両方が利用できる場合、共有ライブラリにリンクされますが、-static オプションを付けることで、リンク時にスタティックライブラリの内容を取り込みます。

スタティックライブラリへリンクすると、バイナリ単体のファイルサイズは、DLL にリンクした場合より大きくなります。しかし、スタティックライブラリとリンクした場合は、必要なオブジェクトファイルのみをバイナリに取り込みますので、通常は、共有ライブラリとリンクしたバイナリ単体と DLL のファイルサイズ合計よりは小さくなります。

同一のライブラリを利用するアプリケーションが多数ある場合、DLL を使えば、ディスク領域を効率的に利用できますが、そうでない場合は、スタティックライブラリを利用した方が効率的な時があります。ビルドするアプリケーションの用途に応じてどちらを利用するか検討する価値はあります。

今回のサンプルで、スタティックライブラリをリンクしてビルドする例を示します。


$ i386-mingw32-gcc -static -Wall grand.c -lgsl -lgslcblas -o grand.e
xe

$ ./grand.exe

-2.488 -0.085 -1.947 -0.206 0.571 1.248 0.211 -0.357 -0.646 -0.023
0.643 -0.707 2.632 1.010 -0.915 -0.894 -0.083 0.303 -0.736 1.284
1.934 -0.477 -0.856 -1.235 -0.380 -0.032 0.076 0.678 -1.175 0.508

(以下省略)

この場合、WINE 環境でも、パスを気にせずバイナリの動作を検証できます。

参考文献


[1] GNU Scientific Library -- Reference Manual
 

0 件のコメント: