ab.com コミュニティ https://www.activebasic.com/forum/ |
|
変数 CharからIntegerへの変換とスピードアップ https://www.activebasic.com/forum/viewtopic.php?t=2634 |
ページ 1 / 1 |
作成者: | ゲスト [ 2010年4月25日(日) 07:56 ] |
記事の件名: | 変数 CharからIntegerへの変換とスピードアップ |
変数の型を最適化してスピードアップを図りたいと思っています。 現在は、Integer型を使用していますが、変数の置き換え、計算等を数多くするので、Char型が有利であろうと考えました。 しかし、一部の計算でChar型を超えてしまう計算が含まれているので、その箇所をIntegerに変換しながら計算する手法としてみました。 しかし、その「変換しながら」にコストがかかってしまい、本末転倒と言いますか、今ひとつの結果になってしまいました。 以下のサンプルで、「*TEST01-00」がInteger同士の計算 「*TEST01-02」がChar型からIntegerへ変換しながらの計算です。 もっと、効率的(スピード的に有利な)方法が、あったらご教授いただければと存じます。 宜しくお願いいたします。 コード: #N88BASIC Dim P%[9,9,59] AS Integer Dim R%[9,9,59] AS Char 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 N=1 Randomize FOR X=1 TO 8 FOR Y=1 TO 8 P%(X,Y,N)=Int(Rnd()*3) R%(X,Y,N)=P%(X,Y,N) AS Char NEXT NEXT PRINT "計算スピードテスト" CT2=20000000 Print Print "Integer(通常)" dwStart = GetTickCount() FOR CT=0 TO CT2:GOSUB *TEST01-00:NEXT PRINT TA1% GOSUB *TIMEPRINT Print "Char(Integerへ変換しながら計算)" dwStart = GetTickCount() FOR CT=0 TO CT2:GOSUB *TEST01-02:NEXT PRINT TA1% GOSUB *TIMEPRINT 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%=(((((((P%[1,8,N]*3+P%[1,7,N])*3+P%[1,6,N])*3+P%[1,5,N])*3+P%[1,4,N])*3+P%[1,3,N])*3+P%[1,2,N])*3+P%[1,1,N]) *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 [/quote] |
作成者: | トモカズ [ 2010年4月25日(日) 07:58 ] |
記事の件名: | 名前を入力し忘れてしまいました |
申し訳ありません。 投稿に名前を入力し忘れてしまいました。 |
作成者: | ぼん [ 2010年4月25日(日) 14:53 ] |
記事の件名: | |
読む気も失せるコードで見てないけど、なんでCharが速いと思ったのだろうか。 どのCPUかわからないけど、32ビットなら32ビット型を54ビットなら64ビット型を使えばいい。 そもそもほんとうにスピードが必要なら、型による速度よりも計算量に気をくばるべきだし、 ABを使うなといいたい。もっと速度の出る処理系を使うべき。 |
作成者: | トモカズ [ 2010年4月25日(日) 16:33 ] |
記事の件名: | |
「読む気も失せる」コードで、申し訳ないです。 (これでも、シンプルにしたつもりです) >なんでCharが速いと思ったのだろうか。 どんなCPUであれ、16Bitより8Bitの方が処理速度について有利だと思ったからです。 違っています?何だかトンチンカンな質問になってしまっているみたいですね。 ごめんなさい。 >計算量に気をくばるべきだし、 もちろん、計算量や計算式の最適化も考えています。 それもやりつつ、型による処理速度向上を考えたわけです。 >ABを使うなといいたい すみません。唯一(どうにか)使えるのがABなのです。 |
作成者: | kobo [ 2010年5月08日(土) 02:12 ] |
記事の件名: | 久々に覗いてみました |
こんばんは。 おそらく、実験的な事を繰り返して頭を捏ねているのかなと勝手に推察します。 云十年前はじめてパソコンに触れていた頃に同じような事をいっぱいしました。 回答だと決め付けられたプログラムを勉強するのではなく 自ら回答を探すからこそ、発想が思わぬ回答を持ち出して愉快になることが 多々あるかと思います。 しかし、トモカズさんは大人ですね。。。これからも頑張ってください。 さてさて、計算速度を上げたいとの事ですが 多次元配列は、何をするにも遅いと聞いた事があります。 ですので、まず第一に多次元配列ではない方法でも実験をされてはいかがでしょうか。 あと、このプログラムを組み込んで行く先の都合にもよりますが、 式を見ると計算の桁数がとても多くなりますね。ですので 必要な時に必要な部分だけ計算をするのも体感速度を上げてくれます。 また、数式を出来るだけ計算しておいてあげるのも一つだと思います。 (x*2)*(x*3)のような式であれば、これを展開しておいたほうが速いかもしれません。 私が、速度を上げる時はパソコン任せの部分を人間が管理することで パソコンの負担を減らしてやるってのが良くやる手です。 多次元でも、メモリの並びは一直線上に並んでいるものと考えて良いそうです。 (10,10)の多次元で(0,0)の場所が0番地だとすると (0,1)は1番地、(0,2)は2番地、(0,9)は9番地となって次の (1,0)は10番地という感じだそうです。 この(x、y)座標とでもいいましょうか。これをメモリの位置に置き換えてくれている分 パソコンは別の仕事をしているようです。 なので、 HeapAllocでメモリを確保して、どこに書き込むかは人間側で計算し管理して 書き込んでいきます。計算もそうやってすることでちょっとは早くなるかもしれませんよ。 確保したメモリはHeapFreeで必ず開放してあげてください。(と良く言われました) でないとプログラムが終了だか電源きるまで確保されたままなので パソコンがフリーズする原因となりかねません(受け売りでーす) 私もN88BASICで育った人間で、ABしかほぼ使えません。 使えるものを全て駆使してやりたいことが出来ればそれで良いと思いますよ。 色々突っ込みどころが満載な返答ですが、上から目線だとか文盲だとかは 重々承知しておりますので、苦笑いでスルーされますようお願い申し上げます。 |
作成者: | ボン [ 2010年5月08日(土) 06:47 ] |
記事の件名: | |
>しかし、トモカズさんは大人ですね。。。これからも頑張ってください。 ガキで悪かったですねえ。。。 >私もN88BASICで育った人間で、ABしかほぼ使えません。 僕もN88-BASICで育った人間ですがね。 >色々突っ込みどころが満載な返答ですが、上から目線だとか文盲だとかは >重々承知しておりますので、苦笑いでスルーされますようお願い申し上げます。 僕に石を投げておいて予防線を張るのはいかがなもんでしょ。 |
作成者: | トモカズ [ 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 [ 2010年5月10日(月) 18:14 ] |
記事の件名: | 私も勉強になりました。 |
こんにちは。 やってみると中々勉強になりました。 トモカズさんのプログラムのしたいことに沿えているか疑問なのですが 書いてみました。 1、計算の基の数値は3まで 2、多次元配列だけど、計算で使うのは1本 3、各項に3の3倍数を順次掛けて足す に注目だけしてみました。 でも、これがFunctionを使うと途端に遅くなるんですね・・・ FORの中に同じ式をほり込んでやるとぐっと早くなるのに。 計算コストとか処理のコストとかはさっぱり分からないですが 私の方ではこんなのを書いてみました。 下記ではFunctionは書いてありますが使っていません。 コード: #N88BASIC Dim d as BytePtr Dim P%[9,9,59] AS Integer Dim R%[9,9,59] AS Byte Dim TA AS DWord Dim X AS Char Dim Y AS Char Dim dwStart AS int64 Dim dwEnd AS int64 Dim TIMECOUNT AS int64 Dim CT AS Int64 Dim CT2 AS Int64 Dim N AS Char N=1 Randomize d=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,9) FOR X=1 TO 8 FOR Y=1 TO 8 P%(X,Y,N)=Int(Rnd()*3) R%(X,Y,N)=P%(X,Y,N) AS Char NEXT '使用する数値は3以下→1バイトでOKと思われる d[X-1]=P%(1,X,N) '場所をずらして頂戴します。 NEXT PRINT "計算スピードテスト" CT2=20000000 Print "Byte" dwStart = GetTickCount() FOR CT=0 TO CT2 'TA=TA + TEST_byte(d) TA=TA +d[0]+d[1]*3+d[2]*9+d[3]*27+d[4]*81+d[5]*243_ +d[6]*729+d[7]*2187 NEXT PRINT TA GOSUB *TIMEPRINT Sleep(-1) END *TIMEPRINT dwEnd = GetTickCount() TIMECOUNT=(dwEnd-dwStart)/100 PRINT TIMECOUNT/10;"秒" RETURN Function TEST_byte(a as BytePtr) as Integer TEST_byte=a[0]+a[1]*3+a[2]*9+a[3]*27+a[4]*81+a[5]*243_ +a[6]*729+a[7]*2187 end Function[/code] |
ページ 1 / 1 | 全ての表示時間は UTC+09:00 です |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |