| CPU | Mobile Celeron 300MHz |
| OS | Linux 2.2.14(Vine Linux 2.0) |
| 数値計算ソフト | GNU Octave, version 2.1.31 |
OctaveにはMatlibのsetround相当の関数がないため、まずそれと同等の関数を作った。 以下のプログラムをsetround.ccという名前で保存し、 "mkoctfile setround.cc"にてsetround.octを作成した。
#include <fpu_control.h>
#include <octave/oct.h>
#include <octave/pager.h>
int _RoundUp = _FPU_DEFAULT | _FPU_RC_UP;
int _RoundDown = _FPU_DEFAULT | _FPU_RC_DOWN;
int _RoundNear = _FPU_DEFAULT | _FPU_RC_NEAREST;
DEFUN_DLD (setround, args, , "The `setround'.")
{
octave_value retval = "OK";
if(args.length() != 1){
octave_stdout << "usage: setround([\"up\"|\"down\"|\"near\"])\n";
retval = "NG";
}else if(args(0).string_value() == "up"){
asm("fldcw _RoundUp");
octave_stdout << "setround ( up )\n";
}else if(args(0).string_value() == "down"){
octave_stdout << "setround ( down )\n";
asm("fldcw _RoundDown");
}else if(args(0).string_value() == "near"){
asm("fldcw _RoundNear");
octave_stdout << "setround ( near )\n";
}else{
octave_stdout << "usage: setround([\"up\"|\"down\"|\"near\"])\n";
retval = "NG";
}
return retval;
}
n = 3
A = rand(n,n)
b = rand(n,1)
R = inv(A)
c = R * b
setround("down")
X1 = R * A - eye(n,n)
setround("up")
X2 = R * A - eye(n,n)
X = max(abs(X1),abs(X2))
D = norm(X,inf)
N = norm(R,inf)
r2 = A * c - b
setround("down")
r1 = A * c - b
k = 1 - D
r = max(abs(r1),abs(r2))
p = norm(r,inf)
setround("up")
e = (N * p) / k
n = 3
A =
0.038796 0.613068 0.599751
0.903270 0.823821 0.162296
0.418286 0.911795 0.482365
b =
0.055407
0.012832
0.792917
R =
3.4901 3.5142 -5.5218
-5.1472 -3.2487 7.4929
6.7031 3.0935 -7.3021
c =
-4.1399
5.6144
-5.3788
setround ( down )
ans = OK
X1 =
-2.2204e-16 -9.9747e-18 -1.1970e-16
8.4568e-18 0.0000e+00 2.8233e-16
-1.3639e-16 2.4720e-16 0.0000e+00
setround ( up )
ans = OK
X2 =
-1.1102e-16 -9.1073e-18 -1.1905e-16
9.1073e-18 2.2204e-16 2.8298e-16
-1.3574e-16 2.4850e-16 2.2204e-16
X =
2.2204e-16 9.9747e-18 1.1970e-16
9.1073e-18 2.2204e-16 2.8298e-16
1.3639e-16 2.4850e-16 2.2204e-16
D = 6.0694e-16
N = 17.099
r2 =
-1.5266e-16
-1.7347e-18
-2.2204e-16
setround ( down )
ans = OK
r1 =
-1.5959e-16
-3.4694e-18
-3.3307e-16
k = 1.00000
r =
1.5959e-16
3.4694e-18
3.3307e-16
p = 3.3307e-16
setround ( up )
ans = OK
e = 5.6950e-15
./configure make su make installで簡単にインストールすることが出来た。
その後、最適化BLAS or ATLASで高速化出来るのを思いだし、最適化BLASを探す。 しかしCeleron(L2Cache=128KB)のBLASが見つからないので、 ATLASをコンパイルすることにした。 寝る前に仕込んでおいたら、さすがに朝にはコンパイル完了。 出来上がったライブラリを/usr/local/libに放り込み、もう一度octaveを作り直した。 その際、config.cache中に
ac_cv_lib_atlas_ATL_xerbla=${ac_cv_lib_atlas_ATL_xerbla='yes'}
という記述があるのを確認。勝手に認識された模様。
再度makeし実行してみると、行列同士のかけ算は10倍程度速くなったが、
A \bは変わらなかった。
File translated from TEX by
TTH, version 2.80 modified by Oishi
On 1 Dec 2000, 09:19.
URI: http://www.oishi.info.waseda.ac.jp/~oishi/accuracy/main.html