1

Python 2.7 (Windows OS 64 ビット) で、参照ポリゴン (Ref) と 1 つ以上のセグメント化された (Seg) ポリゴンから ESRIシェープファイル形式で交差領域の平均値を計算する関数を作成しました。2000 を超える参照ポリゴンがあり、Ref_polygon ごとにすべての Seg ポリゴン (7000 以上) に対して毎回関数が実行されるため、コードは非常に遅くなります。申し訳ありませんが、関数はプロトタイプです。

マルチプロセッシングがループの速度を上げるのに役立つかどうか、または他のパフォーマンス ソリューションがあるかどうかを知りたいです。マルチプロセッシングが可能な解決策である場合、次の関数を最適化する最良の方法を知りたい

import numpy as np
import ogr
import osr,gdal
from shapely.geometry import Polygon
from shapely.geometry import Point
import osgeo.gdal
import osgeo.gdal as gdal

def AreaInter(reference,segmented,outFile):
     # open shapefile
     ref = osgeo.ogr.Open(reference)
     if ref is None:
          raise SystemExit('Unable to open %s' % reference)
     seg = osgeo.ogr.Open(segmented)
     if seg is None:
          raise SystemExit('Unable to open %s' % segmented)
     ref_layer = ref.GetLayer()
     seg_layer = seg.GetLayer()
     # create outfile
     if not os.path.split(outFile)[0]:
          file_path, file_name_ext = os.path.split(os.path.abspath(reference))
          outFile_filename = os.path.splitext(os.path.basename(outFile))[0]
          file_out = open(os.path.abspath("{0}\\{1}.txt".format(file_path, outFile_filename)), "w")
     else:
          file_path_name, file_ext = os.path.splitext(outFile)
          file_out = open(os.path.abspath("{0}.txt".format(file_path_name)), "w")
     # For each reference objects-i
     for index in xrange(ref_layer.GetFeatureCount()):
          ref_feature = ref_layer.GetFeature(index)
          # get FID (=Feature ID)
          FID = str(ref_feature.GetFID())
          ref_geometry = ref_feature.GetGeometryRef()
          pts = ref_geometry.GetGeometryRef(0)
          points = []
          for p in xrange(pts.GetPointCount()):
               points.append((pts.GetX(p), pts.GetY(p)))
          # convert in a shapely polygon
          ref_polygon = Polygon(points)
          # get the area
          ref_Area = ref_polygon.area
          # create an empty list               
          Area_seg, Area_intersect = ([] for _ in range(2))
          # For each segmented objects-j
          for segment in xrange(seg_layer.GetFeatureCount()):
               seg_feature = seg_layer.GetFeature(segment)
               seg_geometry = seg_feature.GetGeometryRef()
               pts = seg_geometry.GetGeometryRef(0)
               points = []
               for p in xrange(pts.GetPointCount()):
                    points.append((pts.GetX(p), pts.GetY(p)))
               seg_polygon = Polygon(points)
               seg_Area.append = seg_polygon.area
               # intersection (overlap) of reference object with the segmented object
               intersect_polygon = ref_polygon.intersection(seg_polygon)
               # area of intersection (= 0, No intersection)
               intersect_Area.append = intersect_polygon.area
          # Avarage for all segmented objects (because 1 or more segmented polygons can  intersect with reference polygon)
          seg_Area_average = numpy.average(seg_Area)
          intersect_Area_average = numpy.average(intersect_Area)
          file_out.write(" ".join(["%s" %i for i in [FID, ref_Area,seg_Area_average,intersect_Area_average]])+ "\n")
     file_out.close()
4

2 に答える 2

6

multiprocessingパッケージ、特にPoolクラスを使用できます。最初に、for ループ内でやりたいことをすべて実行し、引数としてインデックスのみを取る関数を作成します。

def process_reference_object(index):
      ref_feature = ref_layer.GetFeature(index)
      # all your code goes here
      return (" ".join(["%s" %i for i in [FID, ref_Area,seg_Area_average,intersect_Area_average]])+ "\n")

これはファイル自体に書き込まないことに注意してください。複数のプロセスが同時に同じファイルに書き込むため、面倒です。代わりに、書き込む必要がある文字列を返します。また、この関数には、ref_layerまたはref_geometry何らかの方法でそれに到達する必要があるオブジェクトがあることに注意してください-それを行う方法はあなた次第です(process_reference_objectそれらで初期化されたクラスのメソッドとして配置することも、定義するだけで醜いものになる可能性もあります)それらはグローバルに)。

次に、プロセス リソースのプールを作成し、以下を使用してすべてのインデックスを実行しますPool.imap_unordered(これにより、必要に応じて各インデックスが別のプロセスに割り当てられます)。

from multiprocessing import Pool
p = Pool()  # run multiple processes
for l in p.imap_unordered(process_reference_object, range(ref_layer.GetFeatureCount())):
    file_out.write(l)

これにより、参照オブジェクトの独立した処理が複数のプロセスにわたって並列化され、ファイルに書き込まれます (任意の順序で注意してください)。

于 2013-01-07T19:10:42.550 に答える
2

スレッド化はある程度役立ちますが、最初にアルゴリズムを単純化できないことを確認する必要があります。2000 の参照ポリゴンのそれぞれを 7000 のセグメント化されたポリゴンに対してチェックしている場合 (おそらく私が誤解したかもしれません)、そこから開始する必要があります。O(n 2 ) で実行されるものは遅くなるので、絶対に交差しないものを取り除くか、速度を上げる他の方法を見つけることができるかもしれません。それ以外の場合、複数のプロセスまたはスレッドを実行しても、データが幾何学的に増加したときに直線的にのみ改善されます。

于 2013-01-07T19:12:05.030 に答える