LoginSignup

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

pythonのforループの高速化

解決したいこと

私が以前書いたQiitaの記事の中にあるpythonスクリプトについてです.この記事内のスクリプトの中に

~(中略)~

for ix in range(cell_dims[0]+1):
    for iy in range(cell_dims[1]+1):
        for iz in range(cell_dims[2]+1):
            x = ix * mesh_pitch[0] + mins[0]
            y = iy * mesh_pitch[1] + mins[1]
            z = iz * mesh_pitch[2] + mins[2]
            points.InsertNextPoint(x, y, z)
structured_base_mesh = vtk.vtkStructuredGrid()

~(中略)~

という記述があるのですが,pythonの3重ループということもあり,問題によっては非常に時間がかかってしまうという問題があります.
できるだけここを高速にしたい場合,どのような手段がありますでしょうか?

pybindなどは使わず,できるだけpythonで完結させたいです.

ご教授の程宜しくおねがいします.

0

2Answer

  • itertoolsを使う
  • 事前に変数代入しておく
  • 変数代入をなくす

といったところでしょうか。

from itertools import product
nx, ny, nz = cell_dims
px, py, pz = mesh_pitch
mx, my, mz = mins
for ix, iy, iz in product(range(nx + 1), range(ny + 1), range(nz + 1)):
    points.InsertNextPoint(ix * px + mx,
                           iy * py + my,
                           iz * pz + mz)

関数にして変数辞書を小さくすれば、多少変わるかもしれません。

from itertools import product

def make_points(nx, ny, nz, px, py, pz, mx, my, mz):
    points = vtk.vtkPoints()
    for ix, iy, iz in product(range(nx + 1), range(ny + 1), range(nz + 1)):
        points.InsertNextPoint(ix * mx + mx, iy * my + my, iz * mz + mz)
    return points

points = make_points(*cell_dims, *mesh_pitch, *mins)
2

Comments

  1. @dwatanabee

    Questioner
    採用させていただきました.
    ありがとうございます.
  2. @dwatanabee

    Questioner
    setDatの存在は知りませんでした...ありがとうございます.
    @_y_sさんのコメントと組み合わせたら実装することが出来ました.
    概して,元のコードに対して3/5程度の計算時間になったみたいです.
    下の記事は後で更新します.
    https://qiita.com/dwatanabee/items/b938b46ef911a43b92ba

numpyを使えるならnumpyで先に座標を作ってしまうのもありかと思います。

import numpy as np
px, py, pz = mesh_pitch
mx, my, mz = cell_dims * mesh_pitch #max
coords = np.stack(np.mgrid[:mx:px, :my:py, :mz:pz], -1).reshape(-1, 3) + mins
for c in coords:
    points.InsertNextPoint(*c)
1

Comments

  1. @dwatanabee

    Questioner
    ありがとうございます.
    numpyのほうが早そうですが,そのまま実装するとエラーになるみたいなので,もう少し試行錯誤してみたいと思います.
  2. 説明不足ですみません。mesh_pitchやcell_dimsをndarrayにしてもらえれば大丈夫だと思います。

    例:`cell_dims = np.array([mesh_size, mesh_size, mesh_size])`
  3. @dwatanabee

    Questioner
    ありがとうございます。
    書き直したらうまくいきました。
    速さはitertoolsとトントンくらいでした。

Your answer might help someone💌