by トモカズ » 2010年5月08日(土) 10:29
koboさん、返信ありがとうございます。
>実験的な事を繰り返して
ご推察の通りです。様々なアイデアを試しつつ試行錯誤を繰り返しています。
それらのアイデアのほとんどがボツになったりしておりますが・・
そんな訳で今回の(処理速度向上の)質問も的外れだったかもしれませんね。
>まず第一に多次元配列ではない方法でも実験をされてはいかがでしょうか。
そうですね。それも検討してみましたがまだ実験するに至っておりませんでした。
結構、X座標 Y座標を使用して配列を参照するケースが多いので、
P%(X,Y) を P%(X*8+Y) とした場合、X*8に処理コストがかかってしまうのでは無いかと却下しておりました。※今回のケースでは*8です。これだと機械語もビットシフトしてくれていればコストはさほど無さそうな気がしてきました。
これも、簡単なサンプルでベンチマークしてみる必要がありそうですね。
>HeapAllocでメモリを確保して、どこに書き込むかは人間側で計算し管理して
>書き込んでいきます。
ちょっと勉強してみます。
>また、数式を出来るだけ計算しておいてあげるのも一つだと思います。
>(x*2)*(x*3)のような式であれば、これを展開しておいたほうが速いかもしれません。
以下のコードを書いてみました。
*TEST01-04のサブルーチンがソレです。予め計算結果を配列に代入しておき、それを参照して累計だけを行うというものです。※今回のケースでは配列に入力されている数値は0~2だけなので・・・
残念ながらこれだと(計算をするよりも)配列を読みに行く時間の方がかかってしまっていました。
(koboさんの書かれている内容と異なった解釈をしているのかもしれません)
中々と難しいものです。
次回は1次元配列を試してみようかと思っております。ご丁寧な解説をありがとうございました。
コード: 全て選択
#N88BASIC
Dim P%[9,9,59] AS Integer
Dim R%[9,9,59] AS Char
Dim Q%[59,9,9] AS Integer '追加
Dim TA1% AS Integer
Dim X AS Char
Dim Y AS Char
Dim I$ AS STRING
Dim dwStart AS int64
Dim dwEnd AS int64
Dim TIMECOUNT AS int64
Dim CT AS Int64
Dim CT2 AS Int64
Dim N AS Char
dim CV1[2] AS Integer '追加
dim CV2[2] AS Integer '追加
dim CV3[2] AS Integer '追加
dim CV4[2] AS Integer '追加
dim CV5[2] AS Integer '追加
dim CV6[2] AS Integer '追加
dim CV7[2] AS Integer '追加
dim CV8[2] AS Integer '追加
'予め計算しておく '追加
FOR N=0 TO 2
CV1[N]=N
CV2[N]=N*3
CV3[N]=N*3^2
CV4[N]=N*3^3
CV5[N]=N*3^4
CV6[N]=N*3^5
CV7[N]=N*3^6
CV8[N]=N*3^7
NEXT
N=1
Randomize
FOR X=1 TO 8
FOR Y=1 TO 8
P%[X,Y,N]=Int(Rnd()*3)
Q%[N,X,Y]=P%[X,Y,N]
R%[X,Y,N]=P%[X,Y,N] AS Char
NEXT
NEXT
PRINT "計算スピードテスト"
CT2=20000000
Print
Gosub *TEST01-00:PRINT TA1%
Gosub *TEST01-01:PRINT TA1% '追加
Gosub *TEST01-02:PRINT TA1%
Gosub *TEST01-03:PRINT TA1% '追加
Gosub *TEST01-04:PRINT TA1% '追加
Print "Integer(通常)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-00:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Integer(通常) 配列順序を入れ替え"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-01:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ全部変換しながら計算)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-02:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ一部変換しながら計算)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-03:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ配列を参照して累計のみ 掛算なし)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-04:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
I$=Input$(1)
END
*TIMEPRINT
dwEnd = GetTickCount()
TIMECOUNT=(dwEnd-dwStart)/100
PRINT TIMECOUNT/10;"秒"
RETURN
*TEST01-00
TA1%=P%[1,1,N]+P%[1,2,N]*3+P%[1,3,N]*9+P%[1,4,N]*27+P%[1,5,N]*81+P%[1,6,N]*243+P%[1,7,N]*729+P%[1,8,N]*2187
RETURN
*TEST01-01
TA1%=Q%[N,1,1]+Q%[N,1,2]*3+Q%[N,1,3]*9+Q%[N,1,4]*27+Q%[N,1,5]*81+Q%[N,1,6]*243+Q%[N,1,7]*729+Q%[N,1,8]*2187
RETURN
*TEST01-02
TA1%=R%[1,1,N] AS Integer+R%[1,2,N] AS Integer*3+R%[1,3,N] AS Integer*9+R%[1,4,N] AS Integer*27+R%[1,5,N] AS Integer*81+R%[1,6,N] AS Integer*243+R%[1,7,N] AS Integer*729+R%[1,8,N] AS Integer*2187
RETURN
*TEST01-03
TA1%=(R%[1,1,N]+R%[1,2,N]*3+R%[1,3,N]*9+R%[1,4,N]*27) AS Integer +R%[1,5,N] AS Integer*81 +R%[1,6,N] AS Integer*243+R%[1,7,N] AS Integer*729+R%[1,8,N] AS Integer*2187
RETURN
*TEST01-04
TA1%=CV1[R%(1,1,N)]+CV2[R%(1,2,N)]+CV3[R%(1,3,N)]+CV4[R%(1,4,N)]+CV5[R%(1,5,N)]+CV6[R%(1,6,N)]+CV7[R%(1,7,N)]+CV8[R%(1,8,N)]
RETURN
koboさん、返信ありがとうございます。
>実験的な事を繰り返して
ご推察の通りです。様々なアイデアを試しつつ試行錯誤を繰り返しています。
それらのアイデアのほとんどがボツになったりしておりますが・・
そんな訳で今回の(処理速度向上の)質問も的外れだったかもしれませんね。
>まず第一に多次元配列ではない方法でも実験をされてはいかがでしょうか。
そうですね。それも検討してみましたがまだ実験するに至っておりませんでした。
結構、X座標 Y座標を使用して配列を参照するケースが多いので、
P%(X,Y) を P%(X*8+Y) とした場合、X*8に処理コストがかかってしまうのでは無いかと却下しておりました。※今回のケースでは*8です。これだと機械語もビットシフトしてくれていればコストはさほど無さそうな気がしてきました。
これも、簡単なサンプルでベンチマークしてみる必要がありそうですね。
>HeapAllocでメモリを確保して、どこに書き込むかは人間側で計算し管理して
>書き込んでいきます。
ちょっと勉強してみます。
>また、数式を出来るだけ計算しておいてあげるのも一つだと思います。
>(x*2)*(x*3)のような式であれば、これを展開しておいたほうが速いかもしれません。
以下のコードを書いてみました。
*TEST01-04のサブルーチンがソレです。予め計算結果を配列に代入しておき、それを参照して累計だけを行うというものです。※今回のケースでは配列に入力されている数値は0~2だけなので・・・
残念ながらこれだと(計算をするよりも)配列を読みに行く時間の方がかかってしまっていました。
(koboさんの書かれている内容と異なった解釈をしているのかもしれません)
中々と難しいものです。
次回は1次元配列を試してみようかと思っております。ご丁寧な解説をありがとうございました。
[code]
#N88BASIC
Dim P%[9,9,59] AS Integer
Dim R%[9,9,59] AS Char
Dim Q%[59,9,9] AS Integer '追加
Dim TA1% AS Integer
Dim X AS Char
Dim Y AS Char
Dim I$ AS STRING
Dim dwStart AS int64
Dim dwEnd AS int64
Dim TIMECOUNT AS int64
Dim CT AS Int64
Dim CT2 AS Int64
Dim N AS Char
dim CV1[2] AS Integer '追加
dim CV2[2] AS Integer '追加
dim CV3[2] AS Integer '追加
dim CV4[2] AS Integer '追加
dim CV5[2] AS Integer '追加
dim CV6[2] AS Integer '追加
dim CV7[2] AS Integer '追加
dim CV8[2] AS Integer '追加
'予め計算しておく '追加
FOR N=0 TO 2
CV1[N]=N
CV2[N]=N*3
CV3[N]=N*3^2
CV4[N]=N*3^3
CV5[N]=N*3^4
CV6[N]=N*3^5
CV7[N]=N*3^6
CV8[N]=N*3^7
NEXT
N=1
Randomize
FOR X=1 TO 8
FOR Y=1 TO 8
P%[X,Y,N]=Int(Rnd()*3)
Q%[N,X,Y]=P%[X,Y,N]
R%[X,Y,N]=P%[X,Y,N] AS Char
NEXT
NEXT
PRINT "計算スピードテスト"
CT2=20000000
Print
Gosub *TEST01-00:PRINT TA1%
Gosub *TEST01-01:PRINT TA1% '追加
Gosub *TEST01-02:PRINT TA1%
Gosub *TEST01-03:PRINT TA1% '追加
Gosub *TEST01-04:PRINT TA1% '追加
Print "Integer(通常)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-00:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Integer(通常) 配列順序を入れ替え"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-01:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ全部変換しながら計算)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-02:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ一部変換しながら計算)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-03:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
Print "Char(Integerへ配列を参照して累計のみ 掛算なし)"
dwStart = GetTickCount()
FOR CT=0 TO CT2:GOSUB *TEST01-04:NEXT
PRINT TA1%
GOSUB *TIMEPRINT
PRINT
I$=Input$(1)
END
*TIMEPRINT
dwEnd = GetTickCount()
TIMECOUNT=(dwEnd-dwStart)/100
PRINT TIMECOUNT/10;"秒"
RETURN
*TEST01-00
TA1%=P%[1,1,N]+P%[1,2,N]*3+P%[1,3,N]*9+P%[1,4,N]*27+P%[1,5,N]*81+P%[1,6,N]*243+P%[1,7,N]*729+P%[1,8,N]*2187
RETURN
*TEST01-01
TA1%=Q%[N,1,1]+Q%[N,1,2]*3+Q%[N,1,3]*9+Q%[N,1,4]*27+Q%[N,1,5]*81+Q%[N,1,6]*243+Q%[N,1,7]*729+Q%[N,1,8]*2187
RETURN
*TEST01-02
TA1%=R%[1,1,N] AS Integer+R%[1,2,N] AS Integer*3+R%[1,3,N] AS Integer*9+R%[1,4,N] AS Integer*27+R%[1,5,N] AS Integer*81+R%[1,6,N] AS Integer*243+R%[1,7,N] AS Integer*729+R%[1,8,N] AS Integer*2187
RETURN
*TEST01-03
TA1%=(R%[1,1,N]+R%[1,2,N]*3+R%[1,3,N]*9+R%[1,4,N]*27) AS Integer +R%[1,5,N] AS Integer*81 +R%[1,6,N] AS Integer*243+R%[1,7,N] AS Integer*729+R%[1,8,N] AS Integer*2187
RETURN
*TEST01-04
TA1%=CV1[R%(1,1,N)]+CV2[R%(1,2,N)]+CV3[R%(1,3,N)]+CV4[R%(1,4,N)]+CV5[R%(1,5,N)]+CV6[R%(1,6,N)]+CV7[R%(1,7,N)]+CV8[R%(1,8,N)]
RETURN
[/code]