去年書いたFortranのコード。自分でもさっぱり覚えていないけれど、 友達のものと"はやさくらべ"をする機会があり、とんでもないミスに気づいた。 気づくのに一年を要したことになる。
まず、1.csvから10000.csvまでのランダムなファイルを作る。中身は連立方程式を成す行列。
#!/usr/bin/python3
# Make random data
import random
import csv
for num in range(1,10001):
dim = random.randint(2,10)
arr = [[0 for i in range(dim+1)] for j in range(dim)]
for col in range (0,dim):
for row in range(0,dim+1):
arr[col][row] = random.randint(-1000,1000)
f = open(str(num)+'.csv', 'w')
writer = csv.writer(f, lineterminator='\n')
writer.writerows(arr)
次に、timeコマンドでで時間を測る。(出力はネックなので捨てている)
#!/bin/bash
time for i in `seq 1 10000`
do
./Simultaneous ./rnddata/$i.csv >/dev/null 2>&1
done
自分の書いたものは異常なほど時間がかかっていた。(自分がuser:30sec、友達は2sec位)なぜだろう??
探しているうちに、次のような行があった。
do ex_m=piv,d
do ex_n=piv,d
if(abs(linior(ex_m,ex_n))==maxval(abs(linior(piv:d,piv:d)))) then
...
この最終行こそが戦犯で、コストの重い計算をdo文の中で繰り返していたので遅かったのだった。 maxval(abs(linior(piv:d,piv:d)))はループ中では変わらないのでループ外で一度計算すれば良い。 ああ、ショック。はずかし。これを修正したらまともな時間で動くようになった。
過去の自分の書いた文章なりスクリプトなりは 見なおしたほうが良い、という教訓を得た。