ファイルの読み込みが遅いのは?

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
トモカズ

ファイルの読み込みが遅いのは?

#1 投稿記事 by トモカズ »

連続の質問で恐縮です。

以下のコードで実行は可能なのですが、読み取り速度が遅いのです。
ActiveBasicの場合だと、この程度のスピードなのでしょうか?
なお、読取ファイルは6560行、10列です。
(読取ファイルは、http://homepage3.nifty.com/ae85fcmxs/re ... ab-22b.lzh の中の "table.dat" です)

もちろん、最新のパソコンであれば全然問題の無い速度ですが(~3秒程度で完了)
Pentium3位だと、1分程度待たされてしまいます。
なお、F-BASIC97(マイナーですね)で同じコードでコンパイルすると,F-BASIC版の方が5倍程度速いのです。 (因みにファイル読取以外は遥かにActiveBasicの方が速いのです)
何かコードの書き方が根本的に誤っているような気がいたします。

改善できるのでしょうか?
是非、ご教授の程、お願いいたします。


#N88BASIC
dim x,y
dim HEN%[6560,7] AS Char
dim OKE%[6560,1] AS Char
dim NO' AS Integer
Open "table.dat" For Input As #1
LOCATE 0,0:PRINT "ファイル読み込み中です。しばらくお待ち下さい"
DO
Input #1,NO ':NO =Val(A$) :PRINT NO;'"---";
y=x:x=Int(NO/6560*100):IF x<>y THEN LOCATE 0,1:PRINT x;"%"
Input #1,HEN%(NO,0)
Input #1,HEN%(NO,1)
Input #1,HEN%(NO,2)
Input #1,HEN%(NO,3)
Input #1,HEN%(NO,4)
Input #1,HEN%(NO,5)
Input #1,HEN%(NO,6)
Input #1,HEN%(NO,7)
Input #1,OKE%(NO,0)
Input #1,OKE%(NO,1)
Loop Until Eof(1) = -1
close #1
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#2 投稿記事 by konisi »

InputやPrint等の文字列を扱うN88BASIC命令はString型を引数にとった気がします。

それと多次元配列は掛け算を使って実現しているので、頻繁に使うと多少重くなると思います。
気にならない程度だと思いますが。
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ゲスト

#3 投稿記事 by ゲスト »

PⅢで動かしましたが、遅いですね。
N88系コマンドのファイル操作は、確かに遅いです。

>>改善できるのでしょうか?
はじめにファイルを全て読み込みます。
下記のコードで、ReadDataにファイルの内容が収録されます。 この後で、カンマと改行を探しながら、配列にコピーすれば高速になると思います。
トモカズ

速くなりました!!

#4 投稿記事 by トモカズ »

ゲストさん、ありがとうございました。

劇的に速くなりました!!
実行速度を測定(ストップウォッチにて測定につき、正確ではありませんが)しましたが、以下の通りでした。

Pentium3  67.7秒かかっていたものが1.8秒 (約37倍)
Pentium4  18.4秒かかっていたものが1.5秒 (約12倍)

体感的にはP3もP4も変わりません。改善前は全然速度が違っていたのが不思議です。
もちろんCPU性能の要因の他にもディスク性能等あるのでしょうが、いずれにしても2秒以内なのでこれ未満のパソコンでも耐えられる処理速度になったと思います。

今回のファイル読取はメインプログラムを実行する前に1回だけの処理なので、ReadDat,FileSize,hFile ,RBytes 等の変数は以降使用しないのでメモリから開放したい(した方が良い?)のですが、いかがでしょうか?

ヘルプ見ましたが、"HeapFree"を使うのかなぁ?なんて思いましたが使用方法がわかりません。

度々恐縮ですが、ご教授の程よろしくお願いいたします。
トモカズ

#5 投稿記事 by トモカズ »

konisiさん、いつも気にかけてくださいましてありがとうございます。

多次元配列の件、実は私もそう思っていたところなのです。
高速化するには(今回のファイル読取とは別件ですが・・)1次元配列に直そうとも思うのですが、配列引数に対して掛算するのと、内部的に(?)掛算をしているのでは、どちらが速いのかなぁなんて考えておりました。
全てを1次元に直すのも結構大変だし、大変な割にはあまり(スピードの)コストダウンにあまりなってない事を想像すると躊躇してしまいます。
間違いなく速くはなるとは思うのですが・・・・
konisi
記事: 893
登録日時: 2005年7月25日(月) 13:27
お住まい: 埼玉県東松山市
連絡する:

#6 投稿記事 by konisi »

時間の測定には、GetTickCount関数が使えると思います。


HeapFreeをじかに書くと読みにくいと思うので

コード: 全て選択

Function LoadFileData(FileName As *Byte) As *Byte
	Dim ReadData    As BytePtr 
	Dim FileSize    As DWord 
	Dim hFile    As HANDLE 
	Dim RBytes    As Long 

	hFile=CreateFile(FileName,GENERIC_READ,0,ByVal 0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0) 
	FileSize=GetFileSize(hFile,NULL) 
	ReadData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,FileSize+1) 
	ReadFile(hFile,ReadData,FileSize,VarPtr(RBytes),ByVal 0) 
	CloseHandle(hFile) 

	LoadFileData=ReadData
End Function

Sub CloseFileData(Data As *Byte)
	HeapFree(GetProcessHeap(),0,Data)
End Sub

Dim ReadData As *Byte

'読み込む
ReadData=LoadFileData("table.dat")

'ここで内容を使う

'最終処理
CloseFileData(ReadData)
のように関数化すれば使いやすいかと思います

ところで自分で掛け算した場合と多次元配列を使った場合の違いについて調べてみたのですが、どうやら掛け算を使うくらいなら多次元配列を使った方がいいようです
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。
ゲスト

#7 投稿記事 by ゲスト »

>>しないのでメモリから開放したい(した方が良い?)のですが、いかがでしょうか?

サブルーチンにして、サブルーチン内で宣言すればローカル変数として自動的に開放されます。
こんな感じで、プログラムの最後(別のファイルを作ってプロジェクトに追加してもOK)において、
メインプログラムでは、

コード: 全て選択

ReadDBFile()
と書けばOKです。(Gosubに相当します。)
本当は引数を付けて構造化した方がお勧めですが、追々勉強してください。
ゲスト

#8 投稿記事 by ゲスト »

konisiさん

時間の測定・・・いい歳のおっさんがパソコンの前でストップウォッチで計測している姿がとても滑稽ですね。
GetTickCount関数ですね。次の機会にはそれを使ってみます。

HeapFreeの件、わざわざサンプルコードの作成までしていただきましてありがとうございます。
また、配列変数につきましても非常に参考になりました。
なるほど!コンパイルした実行ファイルを見るとそうなのですね。
逆アセンブルというヤツでしょうか?
うーん。私が機械語をやっていた時はZ80 & 6809なので雰囲気は理解できますが、(大昔の事なので忘れかけておりますし)難解です。
私の時代(20数年前)ではハンドアセンブルが主流(私だけだったかな?)紙にコードを書いてから、直接16進入力したものです。20年前にはさすがにソフトウェアによるアセンブラを使用しておりました。

ゲストさん

私もWin32プログラミング講座は目は通しているのですが、頭では理解したつもりでも構造体になじんでおりません。ついgosubを使ってしまうのです。
しかし、お陰様で配列のメモリ開放の件、理解出来ました。
sub(や構造化についても)の習慣を付け、少しづつ慣れていくしかなさそうです。
ありがとうございました。
トモカズ

#9 投稿記事 by トモカズ »

上記自分の名前を入力し忘れました。失礼いたしました
返信する