0

次のコードがあります。

for stepi in range(0, nsteps): #number of steps (each step contains a number of frames)
    stepName = odb.steps.values()[stepi].name #step name
    for framei in range(0, len(odb.steps[stepName].frames)): #loop over the frames of stepi
        for v in odb.steps[stepName].frames[framei].fieldOutputs['UT'].values: #for each framei get the displacement (UT) results for each node
            for line in nodes: #nodes is a list with data of nodes (nodeID, x coordinate, y coordinate and z coordinate)
                nodeID, x, y, z = line
                if int(nodeID)==int(v.nodeLabel): #if nodeID in nodes = nodeID in results
                    if float(x)==float(coordXF) and float(y)==float(coordYF): #if x=predifined value X and y=predifined value Y
                        #Criteria 1: Find maximum displacement for x=X and y=Y
                        if abs(v.data[0]) >uFmax: #maximum UX
                            uFmax=abs(v.data[0])
                            tuFmax='U1'
                            stepuFmax=stepi
                            nodeuFmax=v.nodeLabel
                            incuFmax=framei
                        if abs(v.data[1]) >uFmax: #maximum UY
                            uFmax=abs(v.data[1])
                            tuFmax='U2'
                            stepuFmax=stepi
                            nodeuFmax=v.nodeLabel
                            incuFmax=framei
                        if abs(v.data[2]) >uFmax: #maximum UZ
                            uFmax=abs(v.data[2])
                            tuFmax='U3'
                            stepuFmax=stepi
                            nodeuFmax=v.nodeLabel 
                            incuFmax=framei
                        #Criteria 2: Find maximum  UX, UY, UZ displacement for x=X and y=Y    
                        if abs(v.data[0]) >u1Fmax: #maximum UX
                            u1Fmax=abs(v.data[0])
                            stepu1Fmax=stepi
                            nodeu1Fmax=v.nodeLabel
                            incu1Fmax=framei
                        if abs(v.data[1]) >u2Fmax: #maximum UY
                            u2Fmax=abs(v.data[1])
                            stepu2Fmax=stepi
                            nodeu2Fmax=v.nodeLabel
                            incu2Fmax=framei
                        if abs(v.data[2]) >u3Fmax: #maximum UZ
                            u3Fmax=abs(v.data[2])
                            stepu3Fmax=stepi
                            nodeu3Fmax=v.nodeLabel 
                            incu3Fmax=framei 
            #Criteria 3: Find maximum  U displacement            
            if abs(v.data[0]) >umax: #maximum UX
                umax=abs(v.data[0])
                tu='U1'
                stepumax=stepi
                nodeumax=v.nodeLabel
                incumax=framei
            if abs(v.data[1]) >umax: #maximum UY
                umax=abs(v.data[1])
                tu='U2'
                stepumax=stepi
                nodeumax=v.nodeLabel
                incumax=framei
            if abs(v.data[2]) >umax: #maximum UZ
                umax=abs(v.data[2])
                tu='U3'
                stepumax=stepi
                nodeumax=v.nodeLabel 
                incumax=framei
            #Criteria 4: Find maximum  UX, UY, UZ displacement    
            if abs(v.data[0]) >u1max: #maximum UX
                u1max=abs(v.data[0])
                stepu1max=stepi
                nodeu1max=v.nodeLabel
                incu1max=framei
            if abs(v.data[1]) >u2max: #maximum UY
                u2max=abs(v.data[1])
                stepu2max=stepi
                nodeu2max=v.nodeLabel
                incu2max=framei
            if abs(v.data[2]) >u3max: #maximum UZ
                u3max=abs(v.data[2])
                stepu3max=stepi
                nodeu3max=v.nodeLabel 
                incu3max=framei 

このコードは、数値解析プログラムによって作成された結果データベース ファイルにアクセスし、特定の異なる基準を指定して、土木構造物の変形形状の最大変位を取得します。問題は、このコードの実行に約 10 分かかることです。os のステップ数nstepsは 1 ~ 4 で、フレーム数 ( framei) は 2000 を超え、の数はnodes10000 を超える可能性があります。このコードを高速化する方法はありますか?

4

5 に答える 5

3

4 つのステップ、2000 フレーム、および 10000 ノードがあるとします。これらの数字に照らして、いくつかのアイデアを次に示します。

node-loop の外に計算を移動します。値がノードごとに変わらない場合は、ノード ループに入る前に値を使用して計算を行います。

ノードの別のデータ構造について考えてみてください。8000 ステップ フレームすべてについて、ノード リスト全体を反復処理します。nodeIDただし、 、x、およびに基づく 2 つの条件テストを満たすノードだけを気にしyます。必要なノードを直接検索できれば、より高速になる可能性があります。例えば:

nodesDict[(nodeID, x, y)] = List of nodes with same NodeID, x, and y.

ステップ フレーム ループの前にノード データを前処理し、必要なすべての変換 (整数への変換など) を行います。

保守性のためのリファクタリング。基本的に同じことを行うコードのチャンクがいくつかありますが、若干の違いがあります。このようなコードを長期にわたって維持することは困難です。なぜなら、似たような構文の気が遠くなるような海の微妙な違いに気付かなければならないからです。別のデータ構造について考えるか、反復を使用してコードの重複を減らす方法を検討してください。このような変更によって必ずしもコードの実行が速くなるわけではありません (また、実行が少し遅くなる可能性もあります) が、コードについてより効果的に推論できるため、通常はトレードオフの価値があります。ボトルネックは。

于 2013-05-22T14:51:14.440 に答える
2

あなたのアルゴリズムは次のようです:

O(nsteps * frames_in_step * values_in_frame * nodes)

O(n^4)これは、要素のサイズに関する事前知識がない場合に要約されます。

ロバートが指摘したように、明らかに、各反復で 1 つのノードのみを使用します。dictのを使用できますnodeID: (x,y,z)。これO(1)により、ノードの取得が可能になります。通常、前処理は次のようになります。

nodes_dict = { nodeID:(x,y,z) for nodeID, x, y, z in nodes }

次に、ループ内で次のように呼び出します。

x, y, z = nodes_dict.get(int(v.nodeLabel))

これにより、複雑さが に軽減されますO(n^3)。アルゴリズムをこれ以上単純化することはできないと思います。

次に、同じ配列項目に数回アクセスしています。これは非常に遅いため、キャッシュできます。v.data[x]各反復で 4 ~ 8 回使用されます。一時変数を使用して、それを 1 だけに減らすことができます。

編集

私のコメントで述べたように、umax = max(v.data)データのすべてのインデックスについて。u1max = max(v.values[0]すべての値に対してu2max = max(v.values[1]とが与えられるとu3max = max(v.values[2]umax = max(u1max, u2max, u3max)

したがって、すべてのループの外側でumax処理が完了した後に処理を配置できます。これを単純に配置します。

if abs(u1max) >umax: #maximum UX
    umax=abs(u1max)
    tu='U1'
    stepumax=stepu1max
    nodeumax=nodeu1max
    incumax=incu1max
if abs(u2max) >umax: #maximum UY
    umax=abs(u2max)
    tu='U2'
    stepumax=stepu2max
    nodeumax=nodeu2max
    incumax=incu2max
if abs(u3max) >umax: #maximum UZ
    umax=abs(u3max)
    tu='U3'
    stepumax=stepu3max
    nodeumax=nodeu3max 
    incumax=incu3max

についても同様ですuFmax

于 2013-05-22T14:54:10.107 に答える
1

umax と u1max の値に応じて、条件 1 と 2 を組み合わせることで、少なくとも計算を節約できます。

if abs(v.data[0]) >uFmax:
    calcs
elif abs(v.data[0] > u1Fmax:
    calcs

データベースを保持するために :memory: を使用していますか?

于 2013-05-22T14:24:28.073 に答える
1

Python 2 を使用している場合は、 http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Use_xrange_instead_of_rangeに従ってに置き換えrangeてみてください。xrange

これは Python 3 には当てはまりません。また、膨大な回数の反復をループする場合にのみ違いが生じます。

于 2013-05-22T14:40:44.973 に答える