1

次のコードを高速化しようとしています。文字列のリストが与えられた場合str_list、文字列を数値 ( unpack) に変換し、この数値をネストされたリストの正しい位置に割り当てようとしていますdata。の寸法dataはおおよそdata[4][20][1024]です。残念ながら、この関数は非常にゆっくりと実行されます。コードは次のとおりです。

for abs_idx in range(nbr_elements):

    # get string
    this_element = str_list[abs_idx]

    # convert into number
    this_element = unpack('d', this_element)[0]

    # calculate the buffer number
    buffer_nbr = abs_idx / NBR_DATA_POINTS_PER_BUFFER_INT

    # calculate the position inside the buffer
    index_in_buffer = abs_idx % NBR_DATA_POINTS_PER_BUFFER_INT

    # write data into correct position
    data[file_idx][buffer_nbr][index_in_buffer] = this_element

さらに遅い次の代替ソリューションも試しました。

# convert each string into a number
unpacked_values = [unpack('d', str_list[j])[0] for j in range(nbr_elements)]
for abs_idx in range(nbr_elements):

    # calculate the buffer number
    buffer_nbr = abs_idx / NBR_DATA_POINTS_PER_BUFFER_INT

    # calculate the position inside the buffer
    index_in_buffer = abs_idx % NBR_DATA_POINTS_PER_BUFFER_INT

    # write data into correct position
    data[file_idx][buffer_nbr][index_in_buffer] = unpacked_values[abs_idx]

驚いたことに、次の実装が最も遅いです (最速だと思っていました)。

# convert each string into a number
unpacked_values = [unpack('d', str_list[j])[0] for j in range(nbr_elements)]

# calculate all buffer numbers at once
buffer_ids = np.arange(nbr_elements) / NBR_DATA_POINTS_PER_BUFFER_INT

# calculate all positions inside the buffer at once
index_in_buffer_id = np.arange(nbr_elements) % NBR_DATA_POINTS_PER_BUFFER_INT

for abs_idx in range(nbr_elements):
    data[file_idx][buffer_ids[abs_idx]][index_in_buffer_id[abs_idx]] = unpacked_values[abs_idx]

連続する実装のパフォーマンスが悪いのはなぜですか? 個々のボトルネックはどこにありますか? また、最初のコードを高速化するにはどうすればよいですか?

編集:私のプロファイリング テストから、次の 2 つのステップがボトルネックです: 実行unpackと への値の割り当てdata。これらのステップをスピードアップする方法はわかりません。

EDIT2:unpack文字列が16進数であるため、使用する必要があります。

EDIT3: values = unpack("d" * n, "".join(str_list)) unpack が遅いという問題を解決します。それでも、トリプル (元の) またはダブル (変更された) ネストされたループを使用したデータへの代入は、50% の時間を消費します。この時間を短縮する方法はありますか?

4

3 に答える 3

1

いくつかの最適化:

  1. すべての刺し傷を一度に開梱します
  2. ループの前にアイテムデータ[file_idx]を取得します

それを試してみてください:

n = len(str_list)
values = unpack("d" * n, "".join(str_list))

a = data[file_idx]

# Just to shorten this code sample
q = NBR_DATA_POINTS_PER_BUFFER_INT

for i in xrange(n):
    a[i / q][i % q] = values[i]

ところで、コードのどの部分に最も時間がかかるかをプロファイリングしましたか?

アップデート:

n = len(str_list)
values = unpack("d" * n, "".join(str_list))

# Just to shorten this code sample
q = NBR_DATA_POINTS_PER_BUFFER_INT

data[file_idx] = [values[i:i+q] for i in xrange(0, n, q)]
于 2012-05-24T18:08:57.310 に答える
1

これはもっと速いですか?いくつかのルックアップを削減し、すべての文字列の番号を含む中間リストを作成する必要はありませんか?

df = data[file_idx]
index = 0
for value in str_list:
    # not sure what unpack does... is there a faster function 
    # that does the same?
    number = unpack('d', value)[0]

    # calculate the buffer number
    buffer_nbr = index / NBR_DATA_POINTS_PER_BUFFER_INT

    # calculate the position inside the buffer
    index_in_buffer = index % NBR_DATA_POINTS_PER_BUFFER_INT

    # write data into correct position
    df[buffer_nbr][index_in_buffer] = number

    index += 1
于 2012-05-24T18:27:05.240 に答える
0

これはどう:

df = data[file_idx]
index = 0
bufnr = 0
buf = df[0]
for value in str_list:
    # not sure what unpack does... is there a faster function 
    # that does the same?
    number = unpack('d', value)[0]

    buf[index] = number

    index += 1

    if index >= NBR_DATA_POINTS_PER_BUFFER_INT:
        index = 0
        bufnr += 1
        buf = df[bufnr]

データがリストではなく辞書である可能性はありますか?

于 2012-05-24T19:32:45.743 に答える