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 步数可能是nsteps1 到 4,帧数(frameinodes

4

5 回答 5

3

你说你有 4 个步骤、2000 帧和 10000 个节点。鉴于这些数字,这里有一些想法:

将计算移到 node-loop 之外。如果值不因节点而异,请在进入节点循环之前使用该值进行计算。

考虑节点的不同数据结构。对于所有 8000 个步骤帧,您遍历整个节点列表。但您只关心满足基于 、 和 的两个条件测试nodeIDx节点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)如果您对任何元素的大小一无所知,这就是总和。

正如罗伯特指出的那样,显然,每次迭代只使用一个节点。您可以使用dictof 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

好吧,您至少可以通过组合标准 1 和 2 来节省一些计算,具体取决于您的 umax 和 u1max 的值

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

您是否使用 :memory: 来保存数据库?

于 2013-05-22T14:24:28.073 回答
1

If you are pulling this data from a file, build a database or use redis to store a sorted set (key-tuple) of the data.

Then just use a query (or in redis, zrank) to retrieve the maximum -- what you appear to have here is a "find the maximum value in a column" function, whereas a database has all of that code pre-built and optimized for you to enjoy at maximum speed.

于 2013-05-22T15:01:43.840 回答
1

如果您使用的是 Python 2,请尝试根据http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Use_xrange_instead_of_rangerange替换xrange

这不适用于 Python 3。并且只有在循环大量迭代时才会有所作为。

于 2013-05-22T14:40:44.973 回答