[解決済み] Pythonで最も高速にアクセスできる構造体的オブジェクトは何ですか?
質問
構造体のような非常に大きなリストにアクセスすることが主なボトルネックになっているコードを最適化しています。 現在、私は読みやすさのために、名前付きタプルを使用しています。 しかし、'timeit' を使用したいくつかの簡単なベンチマークは、パフォーマンスが要因である場合、これは本当に間違った方法であることを示しました。
a、b、cの名前付きタプルです。
>>> timeit("z = a.c", "from __main__ import a")
0.38655471766332994
を使ったクラス
__slots__
で,a,b,cで構成されています.
>>> timeit("z = b.c", "from __main__ import b")
0.14527461047146062
a, b, cをキーとする辞書。
>>> timeit("z = c['c']", "from __main__ import c")
0.11588272541098377
定数キーを用いた、3つの値を持つタプル。
>>> timeit("z = d[2]", "from __main__ import d")
0.11106188992948773
定数キーを用いた3つの値を持つリスト。
>>> timeit("z = e[2]", "from __main__ import e")
0.086038238242508669
3つの値を持つタプル、ローカルキーを使用。
>>> timeit("z = d[key]", "from __main__ import d, key")
0.11187358437882722
ローカルキーを使って、3つの値を持つリスト。
>>> timeit("z = e[key]", "from __main__ import e, key")
0.088604143037173344
まず最初に、これらの小さな
timeit
テストが無効になってしまうようなことはありませんか? ランダムなシステム イベントによって無効になっていないことを確認するために、それぞれを数回実行しましたが、結果はほとんど同じでした。
辞書はパフォーマンスと読みやすさの間で最も良いバランスを提供し、クラスはその次に来るようです。 私の目的のために、私はオブジェクトがシーケンスのようになることを必要とするので、これは残念なことです。
リストは実質的に高速ですが、定数キーは維持できません。私は、KEY_1 = 1、KEY_2 = 2、などといったインデックス定数の束を作成しなければなりませんが、これも理想的ではありません。
私はこれらの選択肢から抜け出せないのでしょうか、それとも私が見逃している代替案があるのでしょうか。
どのように解決するのですか?
注意点としては、namedtuplesはタプルとしてアクセスするために最適化されていることです。 もし、アクセッサを
a[2]
の代わりに
a.c
のようにすれば、タプルと同様のパフォーマンスが得られるでしょう。 その理由は、名前アクセスは事実上 self[idx] の呼び出しに変換されるため、インデックス作成と
と
の両方を支払うことになるからです。
名前によるアクセスはよくあるが、タプルとしてのアクセスはあまりない、というような使用パターンであれば は は、namedtupleと同等のものを素早く書いて、逆の方法で物事を行うことができます。 しかし、その場合、インデックス検索で代償を払うことになります。 例えば、ここに簡単な実装があります。
def makestruct(name, fields):
fields = fields.split()
import textwrap
template = textwrap.dedent("""\
class {name}(object):
__slots__ = {fields!r}
def __init__(self, {args}):
{self_fields} = {args}
def __getitem__(self, idx):
return getattr(self, fields[idx])
""").format(
name=name,
fields=fields,
args=','.join(fields),
self_fields=','.join('self.' + f for f in fields))
d = {'fields': fields}
exec template in d
return d[name]
しかし、次のような場合、タイミングが非常に悪くなります。
__getitem__
が呼び出されなければなりません。
namedtuple.a : 0.473686933517
namedtuple[0] : 0.180409193039
struct.a : 0.180846214294
struct[0] : 1.32191514969
と同じ性能で
__slots__
クラスと同じ性能ですが、インデックスベースのアクセスでは二重ルックアップのために大きなペナルティーが発生します。 (注目すべきは
__slots__
は実際には速度的にはあまり役に立ちません。 それはメモリを節約しますが、アクセス時間はそれらなしでほぼ同じです)。
たとえば、リストからサブクラスを作成し、値を属性とリストデータの両方に保存します。 しかし、実際にはリストと同等のパフォーマンスを得ることはできません。 サブクラスを作成しただけで、大きな速度低下が発生します(pure-pythonのオーバーロードのチェックが入る)。 したがって、この場合でも struct[0] には約 0.5 秒かかり(生のリストでは 0.18 秒)、メモリ使用量も 2 倍になるので、これはあまり意味がないかもしれません。
関連
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] Pythonでオブジェクトが属性を持つかどうかを知る方法
-
[解決済み] オブジェクトの種類を決定しますか?
-
[解決済み] Python 3 の "python -m SimpleHTTPServer" に相当するものは何ですか?
-
[解決済み] Pythonでnullオブジェクトを参照する
-
[解決済み】__str__と__repr__の違いは何ですか?
-
[解決済み] pycharmがタブをスペースに自動変換する
-
[解決済み] 単純な文字列からtimedeltaオブジェクトを作成する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pythonの「名前付きタプル」とは何ですか?
-
[解決済み] Djangoで2つの日付の間を選択する
-
[解決済み] Spyderを仮想環境で動作させるには?
-
[解決済み] dict を txt ファイルに書き、それを読み取る?
-
[解決済み] Python 2.7サポート終了?
-
[解決済み] 値で列挙名を取得する [重複]。
-
[解決済み] Django で全てのリクエストヘッダを取得するにはどうすれば良いですか?
-
[解決済み] Python 言語を決定するには?
-
[解決済み] Pythonでランダムなファイル名を生成する最良の方法
-
[解決済み] Python の sorted() はどのようなアルゴリズムを使っているのですか?重複