[リストへもどる]
一括表示

投稿時間:2004/06/10(Thu) 19:11
投稿者名:まんたろー
URL :
タイトル:
文字列連結の高速化
暇な方

文字列連結の高速化の競争しましょう。
以下のコードの高速化をしてみてください。
Private Function func()
    Dim i As Long
    Dim tmp As string
    For i = 0 To 100000
        tmp = tmp & CStr(i)
    Next i
    func = tmp
End Function

計測は以下の方法で
Private Sub Command1_Click()
    Dim tm As Double
    Dim data As String
    tm = Timer
    data = func
    MsgBox Timer - tm
End Sub

ハードの性能に依存するので、高速化前/後の倍率で勝負です。

私の記録です。

前:108.26秒
後:0.22秒
約492倍

環境:Win2000
     VB6

方法は後ほど書きます。
それでは皆さんがんばりましょう

投稿時間:2004/06/10(Thu) 19:33
投稿者名:とうきちろう
Eメール:
URL :
タイトル:
Re: 文字列連結の高速化
前:113.77秒
後:3.30秒
約34.48倍

環境:Win2000
VB6

Const MAX_VALUE = 100000
Const END_OF_LOOP = (MAX_VALUE / 5&) - 1&

Const ADD_VALUE = 55555
Const INITIAL_VALUE = 12345&

Private Sub Command1_Click()
    Dim tm As Long
    Dim data As String
    
    tm = Timer
    
    data = func
    
    MsgBox Timer - tm
End Sub

Private Function func()
    Dim i As Long

    Dim sCurrStr As String
    Dim lCurrVal As Long

    Dim lLoop As Long

    lCurrVal = INITIAL_VALUE

    For lLoop = 1 To END_OF_LOOP
       sCurrStr = sCurrStr & CStr(lCurrVal)
       lCurrVal = lCurrVal + ADD_VALUE
    Next

    func = sCurrStr
End Function

投稿時間:2004/06/10(Thu) 19:40
投稿者名:まんたろー
URL :
タイトル:
Re^2: 文字列連結の高速化
とうきちろう君
なかなか面白い方法ですね。
ッていうか、出力される文字列が元と違うじゃん。
コードの意図がさっぱり読み取れません。
これは乱数を発生させている訳ではありませんので、
結果も元と同じようにね。

投稿時間:2004/06/10(Thu) 22:28
投稿者名:Say
Eメール:
URL :
タイトル:
Re: 文字列連結の高速化
文字列連結が遅いのは、ブロック転送が多発するためです。


VB6の機能限定ならおそらく、
「Mid$ステートメントでの置換」が最速で、
「配列に入れてJoin」が次点ってところでしょうか。

方法を問わないなら、C/C++でそういうdllを作って呼ぶ、
という手もありますが、100000回程度のループなら
Mid$ステートメントで0.1秒程度の処理でしょうから、
dll呼び出しのコストで帳消しになりそうな・・・。
もっと時間がかかる処理なら
言語による速度差が明確に出るのでしょうが。

投稿時間:2004/06/11(Fri) 00:08
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^2: 文字列連結の高速化
> 方法を問わないなら

結果が常に一定の文字列なので、結果の代入だけなら 0.08秒でした。(^^;)


ま、それは反則として。
ループで作成するなら、結果を一時ファイルに吐いて、
それを一括してGet#→StrConvする手法で 0.36秒でした。

また、常套手段なJoin法、Midステートメント法は、それぞれ0.52秒、0.28秒でした。

# 高速化前コードの実行時間は内緒。(謎

投稿時間:2004/06/11(Fri) 01:09
投稿者名:Say
Eメール:
URL :
タイトル:
Re^3: 文字列連結の高速化
> > 方法を問わないなら
> 結果が常に一定の文字列なので、結果の代入だけなら 0.08秒でした。(^^;)

魔界の仮面弁士さんに座布団1枚。

投稿時間:2004/06/11(Fri) 00:16
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: 文字列連結の高速化
Join 法 0.15 秒 Mid 法 0.11 秒  元々 150 秒

投稿時間:2004/06/11(Fri) 09:27
投稿者名:まんたろー
URL :
タイトル:
Re: 文字列連結の高速化
やっぱり、みんな考えることは同じですね。
私はJoinでやりました。

一番突飛な方法はとうきちろうさんの方法ですね。
解を無視して、ループ回数を減らしてしまうとは、
常人の思いつくことでは無いですから。

何かすごい方法とか無いんですかね?

投稿時間:2004/06/11(Fri) 20:38
投稿者名:Say
Eメール:
URL :
タイトル:
Re^2: 文字列連結の高速化
> 何かすごい方法とか無いんですかね?
「常套手段」というやつは、それなりに試した結果
常套手段になっているわけですから・・・。

すごくはないけど、VBにしてはちょっとひねたやり方をひとつ・・・
Cならポインタ使って、もうちょっとましな書き方ができますが。

(あんまり吟味してないんで、バグってるかも。
再帰にすればコードは簡単になりますが、処理は遅くなるでしょう。)

Private Function func()
Dim i1 As Long
Dim i2 As Long
Dim i3 As Long
Dim i4 As Long
Dim i5 As Long
Dim i6 As Long
Dim j As Long
Dim tmp(100000 * 6& * 4) As Byte
For i1 = 0& To 9&
    tmp(i1 * 2&) = 48 + i1
Next
For i1 = 1& To 9&
    For i2 = 0& To 9
        j = (i1 * 10& + i2) * 4& - 20&
        tmp(j) = 48& + i1
        tmp(j + 2&) = 48& + i2
    Next
Next
For i1 = 1& To 9&
    For i2 = 0& To 9&
        For i3 = 0& To 9&
            j = (i1 * 100& + i2 * 10& + i3) * 6& - 220&
            tmp(j) = 48& + i1
            tmp(j + 2&) = 48& + i2
            tmp(j + 4&) = 48& + i3
        Next
    Next
Next
For i1 = 1& To 9&
    For i2 = 0& To 9&
        For i3 = 0& To 9&
            For i4 = 0& To 9&
                j = (i1 * 1000& + i2 * 100& + i3 * 10& + i4) * 8& - 2220&
                tmp(j) = 48& + i1
                tmp(j + 2&) = 48& + i2
                tmp(j + 4&) = 48& + i3
                tmp(j + 6&) = 48& + i4
            Next
        Next
    Next
Next
For i1 = 1& To 9&
    For i2 = 0& To 9&
        For i3 = 0& To 9&
            For i4 = 0& To 9&
                For i5 = 0& To 9&
                    j = (i1 * 10000& + i2 * 1000& + i3 * 100& + i4 * 10& + i5) * 10& - 22220&
                    tmp(j) = 48& + i1
                    tmp(j + 2&) = 48& + i2
                    tmp(j + 4&) = 48& + i3
                    tmp(j + 6&) = 48& + i4
                    tmp(j + 8&) = 48& + i5
                Next
            Next
        Next
    Next
Next
j = j + 10&
tmp(j) = 49
tmp(j + 2&) = 48
tmp(j + 4&) = 48
tmp(j + 6&) = 48
tmp(j + 8&) = 48
tmp(j + 10&) = 48
func = tmp()
End Function

投稿時間:2004/06/13(Sun) 18:42
投稿者名:まんたろー
URL :
タイトル:
Re^3: 文字列連結の高速化
Say さん
はやいですねー。

シーケンシャルな文字列連結にはいいですね。

皆さんお付き合いいただき、お疲れ様でした。
それでは。