【问题标题】:Python optimization of 3D grid search with nested loops使用嵌套循环对 3D 网格搜索进行 Python 优化
【发布时间】:2016-04-22 08:10:07
【问题描述】:

假设我们有一个带有离散点的 3D 网格。 3 个维度(包括区间端点)的范围是:

在 x 中:[4000, 7000],在 y 中步长 1000:[0.0, 2.0],在 z 中步长 1.0:[-0.75, 0.75],步长 0.25

现在应该对 [4000, 7000, 100], [0.0, 2.0, 0.1], [-0.75, 0.75, 0.05] 范围内的所有点完成以下任务(大约 20000 = 31 * 21 * 31 点):

找到包含该点的最小长方体。然而,网格中有孔(每个点都应该有一个“物理”对应的文件,但有些没有)。我尝试了以下非常简单的代码(我将长方体称为“立方体”):

def findcubesnew(startvalues, endvalues, resols, \
  loopvalues, refvalues, modelpath):

  cubearray = []
  startvalue1 = startvalues[0]
  endvalue1 = endvalues[0]
  resol1 = resols[0]
  refvalue1 = refvalues[0]
  loopstop1 = loopvalues[0][0]
  loopstart1 = loopvalues[1][0]
  startvalue2 = startvalues[1]
  endvalue2 = endvalues[1]
  resol2 = resols[1]
  refvalue2 = refvalues[1]
  loopstop2 = loopvalues[0][1]
  loopstart2 = loopvalues[1][1]
  startvalue3 = startvalues[2]
  endvalue3 = endvalues[2]
  resol3 = resols[2]
  refvalue3 = refvalues[2]
  loopstop3 = loopvalues[0][2]
  loopstart3 = loopvalues[1][2]
  refmass = refvalues[3]
  refveloc = refvalues[4]

  for start1 in numpy.arange(startvalue1, loopstop1 + resol1, resol1):
    for end1 in numpy.arange(loopstart1, endvalue1 + resol1, resol1):
      for start2 in numpy.arange(startvalue2, loopstop2 + resol2, resol2):
        for end2 in numpy.arange(loopstart2, endvalue2 + resol2, resol2):
          for start3 in numpy.arange(startvalue3, loopstop3 + resol3, resol3):
            for end3 in numpy.arange(loopstart3, endvalue3 + resol3, resol3):
              if glob.glob(*start1*start2*start3) and \
                if glob.glob(modelpath/*start1*start2*end3) and \
                if glob.glob(modelpath/*start1*end2*start3) and \
                if glob.glob(modelpath/*start1*end2*end3) and \
                if glob.glob(modelpath/*end1*start2*start3) and \
                if glob.glob(modelpath/*end1*start2*end3) and \
                if glob.glob(modelpath/*end1*end2*start3) and \
                if glob.glob(modelpath/*end1*end2*end3):
                  cubearray.append((start1, end1, start2, end2, start3, end3))
                else:
                  pass
  return cubearray

foundcubearray = findcubesnew([metalstart, tempstart, loggstart], \
  [metalend, tempend, loggend], [metalresol, tempresol, loggresol], \
  looplimitarray, [refmetal, reftemp, reflogg, refmass, refveloc], \
  modelpath)
if foundcubearray:
  bestcube = findsmallestcubenew(foundcubearray, \
    [metalresol, tempresol, loggresol])
  ....

因此,我在 x 方向上从较低的网格边界到我们想要获取长方体的所需点下方的最大值进行循环,并在另一个循环中从该点之后的最小值到较高的网格边界。类似地,对于 y 方向和 z 方向,循环彼此嵌套。 if 部分是没有格式字符串等的伪代码,并检查具有这些值的所有文件(文件名中可能还有其他数量)确实存在(长方体的所有角都存在)。

如果点的一个或多个坐标与我们网格中的值重合,此代码还会找到点、线或矩形,但这不是问题(并且实际上是需要的)。

这里的瓶颈是搜索长方体需要相当长的时间(然后可以轻松快速地找到最小的长方体,如果有多个相同(最小)大小的长方体,我不在乎选择哪一个)。我还需要读取网格的开始值和结束值、步长、我的点的参考值(坐标)和其他一些变量。有什么办法可以优化代码?每点大约需要 1.4 秒,所以 ~ 20000 点需要 8 小时,这太长了。

我知道如果我找到最小的长方体,例如对于点 4500, 0.5, 0.1,我可以立即看出立方体内的所有其他点的限制为 [4000, 5000; 0.0, 1.0; 0, 0.25] 具有相同的最小长方体。我仍然对优化所有 20000 次运行的计算时间的解决方案感兴趣。它的应用是恒星模型的插值程序,其中需要在插值点周围有 8 个长方体形状的网格点。

P.S.:我希望续行换行和缩进是正确的。在我的代码中它们不存在,尽管每行超过 80 个字符并不是一种好的风格:)。

【问题讨论】:

    标签: python for-loop optimization


    【解决方案1】:

    我的建议是不要使用 glob。如果我没看错,modelpath 目录最多可以包含 20,000 个文件,在内循环体中可能有 8 个 glob。我很惊讶每点只需要 1.4 秒!

    文件名只是用作布尔值,对吗?重要的是文件是否存在。

    我将创建一个 3D 布尔数组,其尺寸与您的 3D 网格相同,初始化为 False。然后通读目录的内容,将每个文件名转换为 3D 索引并将其设置为 True。

    然后使用布尔数组而不是文件系统搜索点。

    希望这会有所帮助。

    【讨论】:

    • 嗯,确实不是 for 循环减慢了程序速度,而是 if 子句...停用 8 倍 if 子句但仍附加坐标导致 ~ 4秒为 20000 个模型。我将尝试您的建议,使用 numpy.zeros((4,3,7)) 创建数组,并从所有 20000 个文件中查找 (84) 个模型,读取文件名“值”,将它们转换为数组索引并设置相应的。数组值为 1。
    • 问题解决了,问题解决了 :) 问题已被标记为已回答...再次感谢
    猜你喜欢
    • 2017-05-28
    • 1970-01-01
    • 2021-01-21
    • 2018-06-19
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    相关资源
    最近更新 更多