วิธีเพิ่มความเร็วให้กับสคริปต์ Python ที่ทำงานเป็นเครื่องมือ ArcGIS [ปิด]


31

นี่เป็นคำถามทั่วไปที่ค่อนข้างสวย ฉันแค่สงสัยว่าเคล็ดลับและเทคนิคที่โปรแกรมเมอร์ GIS ใช้เพื่อเพิ่มความเร็วสคริปต์อาร์คกิที่คุณนำเข้าสู่กล่องเครื่องมือและเรียกใช้

ฉันทำงานเขียนสคริปต์เล็กน้อยทุกวันเพื่อช่วยผู้ใช้ที่ไม่ใช่ GIS ในสำนักงานเพื่อประมวลผลข้อมูล GIS ฉันได้พบว่าการประมวลผล ArcGIS 10.0 โดยทั่วไปช้ากว่า 9.3.1 และบางครั้งมันก็ช้าลงเมื่อใช้งานสคริปต์ไพ ธ อน

ฉันจะแสดงรายการตัวอย่างของสคริปต์ที่ใช้เวลานานกว่า 24 ชั่วโมงในการทำงาน มันคือลูปที่กำหนดพื้นที่ของแรสเตอร์ในบัฟเฟอร์สำหรับแต่ละรูปร่างในบัฟเฟอร์ บัฟเฟอร์มีรูปร่างประมาณ 7000 ฉันไม่เชื่อว่ามันจะทำงานได้นาน

while x <= layerRecords:

    arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
    arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
    TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

    arcpy.AddMessage ("          - Row: " + str(x) + " completed")
    x = x + 1
    z = z + 1

ก่อนที่ทุกคนจะพูดว่าฉันได้เรียกใช้ตารางพื้นที่ในบัฟเฟอร์ทั้งหมด แต่มันก่อให้เกิดข้อผิดพลาดถ้าทำงานมากกว่า 1 บันทึก มันเป็นเครื่องมือที่มีตำหนิ แต่ฉันต้องใช้มัน

อย่างไรก็ตามหากใครมีแนวคิดใด ๆ เกี่ยวกับวิธีการเพิ่มประสิทธิภาพหรือเพิ่มความเร็วของสคริปต์นี้ก็จะได้รับการชื่นชมมากที่สุด มิฉะนั้นคุณจะมีเทคนิคเร่งความเร็วสำหรับงูใหญ่เมื่อใช้ใน ArcGIS?

คำตอบ:


26

คำแนะนำที่เป็นไปได้สองสามข้อเพื่อช่วยเร่งกระบวนการของคุณคือ:

  1. เลือกเลเยอร์โดยคุณสมบัติสามารถอยู่ในสคริปต์ Python เท่านั้นโดยไม่ต้องเปิด ArcGIS Desktop คุณต้องแปลงการอ้างอิง "buff" ของคุณจากการอ้างอิงแบบไฟล์เป็นการอ้างอิง "เลเยอร์ ArcGIS" ซึ่ง ArcGIS สามารถประมวลผลการสืบค้นที่เลือก ใช้arcpy.MakeFeatureLayer_management ("buff", "buff_lyr") เหนือ "ห่วง" ในขณะที่ "ของคุณแล้วเปลี่ยนการอ้างอิงของคุณด้านล่างห่วงขณะที่จะใช้" buff_lyr "

  2. ประมวลผลการดำเนินงาน GP ของคุณให้มากที่สุดโดยใช้พื้นที่ทำงาน in_memoryเท่าที่จะเป็นไปได้ ... ใช้ arcpy.CopyFeatures_management (shapefile, "in_memory \ memFeatureClass") เพื่อย้ายแหล่งของคุณไปยังหน่วยความจำ วิธีนี้ใช้งานได้ดีถ้าคุณมี RAM เพียงพอที่จะอ่านคลาสคุณลักษณะทั้งหมดที่คุณต้องการในหน่วยความจำ อย่างไรก็ตามระวังว่ามีการดำเนินการ GP บางอย่างที่ไม่สามารถเรียกใช้โดยใช้พื้นที่ทำงาน in_memory (เช่น: เครื่องมือโครงการ)

จากบทความช่วยเหลือแบบออนไลน์ของ ArcGIS 9.3 " ข้อมูลระดับกลางและพื้นที่ใช้งานรอยขีดข่วน " (หมายเหตุภาษานี้ถูกลบออกจากความช่วยเหลือ 10.0 และ 10.1):

หมายเหตุ: เฉพาะตารางและคุณลักษณะคลาส (จุดเส้นรูปหลายเหลี่ยม) เท่านั้นที่สามารถเขียนไปยังพื้นที่ทำงาน in_memory พื้นที่ทำงาน in_memory ไม่สนับสนุนองค์ประกอบทางภูมิศาสตร์ฐานข้อมูลเพิ่มเติมเช่นชนิดย่อยโดเมนการแทนค่าโทโพโลยีเครือข่ายทางเรขาคณิตและชุดข้อมูลเครือข่าย สามารถเขียนได้เฉพาะคุณสมบัติและตารางอย่างง่าย

จากบทความช่วยเหลือออนไลน์ ArcGIS 10.1 " การใช้พื้นที่ทำงานในหน่วยความจำ ":

ข้อควรพิจารณาต่อไปนี้ต้องตัดสินใจในการตัดสินใจเขียนเอาต์พุตไปยังพื้นที่ใช้งานในหน่วยความจำ:

  • ข้อมูลที่เขียนไปยังพื้นที่ใช้งานในหน่วยความจำชั่วคราวและจะถูกลบเมื่อปิดแอปพลิเคชัน
  • ตารางคลาสคุณสมบัติและ rasters สามารถเขียนไปยังพื้นที่ทำงานในหน่วยความจำ
  • เวิร์กสเปซในหน่วยความจำไม่สนับสนุนองค์ประกอบทางภูมิศาสตร์ฐานข้อมูลเพิ่มเติมเช่นชนิดย่อยโดเมนการแทนค่าโทโพโลยีเครือข่ายทางเรขาคณิตและชุดข้อมูลเครือข่าย
  • ไม่สามารถสร้างชุดข้อมูลหรือโฟลเดอร์คุณสมบัติในพื้นที่ทำงานในหน่วยความจำ

1
มันอัศจรรย์มาก! ฉันกำลังมองหาวิธีใช้ตัวเลือกนอก ArcMap แต่ยังไม่ประสบความสำเร็จ ในแง่ของปัญหานี้จริง ๆ แล้วมันผลักเวลาของฉันต่อแถวลงไปประมาณ 13 วินาทีจาก 20 วินาที แต่ฉันทำงานอื่น ๆ อย่างรวดเร็วและใช้ MakeFeatureLayer ภายในลูปและลดลงเหลือ 9 วินาที ฉันทำสิ่งนี้โดยการสร้างคุณลักษณะจากแต่ละรูปร่างมากกว่าการทำเป็นตารางจากเลเยอร์คุณลักษณะ ฉันยังอยากจะทำให้มันแย่ลงไปอีกถ้าเป็นไปได้ แต่มันก็เป็นกระบวนการที่เร็วกว่ามาก!
โคดี้บราวน์

ดังที่กล่าวไว้ใน # 2 ใช้ CopyFeatures เพื่อทำสำเนาของแหล่งข้อมูลของคุณในหน่วยความจำจากนั้นสร้าง feature_layer ของคุณกับแหล่ง in_memory ในขณะที่สำเนาเริ่มต้นไปยังหน่วยความจำอาจเพิ่มสองสามวินาทีล่วงหน้าคุณอาจพบว่าการประมวลผลของ copyfeatures + tabulate_areas จะมีเวลาประมวลผลรวมเร็วกว่ารุ่นปัจจุบันของคุณ
RyanDalton

ฉันลองมันด้วยและดูเหมือนว่าวิธีแก้ปัญหานั้นจะทำให้กระบวนการวนเร็วขึ้น แต่ก็ไม่เป็นเช่นนั้น การสร้างเลเยอร์ฟีเจอร์ในลูปจะให้ผลลัพธ์ประมาณ 8-10 วินาทีต่อลูปในขณะที่การสร้างเลเยอร์ฟีเจอร์ก่อนที่ลูปจะให้ผลลัพธ์ใน 11 - 14 วินาทีต่อการวนซ้ำ ฉันไม่แน่ใจเหมือนกันว่าเพราะเหตุใดโซลูชันของคุณจึงดูเหมือนว่าจะดำเนินการเร็วขึ้น ฉันมี RAM 8GB ดังนั้นฉันสงสัยว่าจะเป็นปัญหา
โคดี้บราวน์

การจัดการกับฟีเจอร์ให้กับ in_memory ก่อนลูปแล้วยังคงสร้างเลเยอร์ฟีเจอร์ในลูปทำให้ประสิทธิภาพการทำงานเร็วขึ้นเล็กน้อย มันค่อนข้างจะอยู่ที่ 8 วินาทีต่อแถวสำหรับแต่ละวง ซึ่งจะลดเวลาในการดำเนินการทั้งหมดจาก 26 ชั่วโมงเป็น 22.
Cody Brown

หลังจากเพิ่มความคิดของคุณสคริปต์ของฉันปรับปรุงขึ้นอย่างมาก ขอบคุณสำหรับความช่วยเหลือของคุณและทุกคน!
โคดี้บราวน์

28

เทคนิคการเพิ่มประสิทธิภาพหลามทั่วไปสามารถช่วยคุณประหยัดเวลาได้มาก

เทคนิคที่ดีอย่างหนึ่งในการลดระดับการหยุดค้างที่สคริปต์ของคุณใช้โมดูล cProfile ในตัว:

from cProfile import run
run("code") # replace code with your code or function

การทดสอบโดยใช้ตัวอย่างข้อมูลขนาดเล็กจะช่วยให้คุณระบุได้ว่าการเรียกใช้ฟังก์ชันใดใช้เวลามากที่สุด

ตัวชี้ทั่วไปสำหรับรหัสหลามที่เร็วกว่า:

  • รายการความเข้าใจโดยทั่วไปจะเร็วกว่าการวนซ้ำ
  • เครื่องกำเนิดไฟฟ้าผลิตรายการในเวลาเดียวแทนที่จะผลิตรายการทั้งหมดในครั้งเดียว
  • ใช้ xrange แทนช่วงใน python 2 (ไม่จำเป็นใน 3)
  • ชุดสามารถออกรายการ preform เมื่อมันมาถึงการกำหนดว่ารายการที่มีอยู่ในชุด แต่โดยทั่วไปจะช้ากว่ารายการเมื่อมันมาซ้ำกว่าเนื้อหาของพวกเขาที่มา
  • การเรียกใช้ฟังก์ชันอาจมีค่าใช้จ่ายสูงต่อประสิทธิภาพของแหล่งที่มา
  • เคล็ดลับและรายละเอียดเพิ่มเติมตรวจสอบได้ที่นี่Python Perfomance Tipsและที่นี่10 Python Optimization Tips และปัญหา

เกี่ยวกับสคริปต์ของคุณฉันไม่สามารถแสดงความคิดเห็นในด้าน ArcPy ได้เนื่องจากฉันไม่ได้ติดตั้ง Arc บนคอมพิวเตอร์เครื่องนี้ แต่คุณอาจต้องการลองใช้ for for loop แทนการวนรอบสักครู่เพื่อดูว่าสิ่งใดดีขึ้นหรือไม่ นอกจากนี้ x = x + 1 สามารถเขียนเป็น x + = 1:

for record in layerRecords:
arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

arcpy.AddMessage ("          - Row: " + str(x) + " completed")
x+=1
y+=1

1
ฉันใช้ลิงก์ทั้งสองที่คุณทิ้งไว้ใน bullet สุดท้ายของคุณและสามารถช่วยสคริปต์ของฉันด้วยการแก้ไขด่วน ๆ
โคดี้บราวน์

หากฉันสามารถให้รางวัลสองคำตอบที่ถูกต้องได้ ในขณะที่คำตอบของคุณเสนอความคิดมากมายเกี่ยวกับวิธีเร่งความเร็วให้กับงูใหญ่ @RyanDalton เสนอแนวคิดที่มีผลกระทบมากที่สุด ขอบคุณตัน!
โคดี้บราวน์

13

ตรวจสอบให้แน่ใจว่าคุณเขียนไปยังไดรฟ์ภายในบนคอมพิวเตอร์ การเข้าถึงเครือข่ายเมื่อไม่จำเป็นอาจทำให้การประมวลผลช้าลง มันสามารถเร็วกว่าในการคัดลอกข้อมูลเป็นขั้นตอนแรกในกระบวนการเพื่อให้การอ่าน - เขียนที่ตามมาเร็วที่สุดเท่าที่จะทำได้

การรันสคริปต์โดยสมบูรณ์นอก ArcMap นั้นเร็วกว่ามาก หากไม่จำเป็นต้องใช้แผนที่ในระหว่างการประมวลผลอย่าใช้ ArcMap


ฉันพบว่าการเรียกใช้สคริปต์ภายในแบบจำลองจาก ArcCatalog (โดยตัวมันเองภายในCalculate Valueกล่องโต้ตอบ) จะดำเนินการได้เร็วกว่าการเรียกใช้สคริปต์เดียวกันจากหน้าต่าง ArcPy ใน ArcMap นั่นเป็นเพียงการสังเกตอย่างหมดจด
Cindy Jayakumar

1
ฉันเชื่อว่าฉันต้องการแผนที่เพื่อให้ Tabulate ทำงานอย่างถูกต้อง แต่ฉันจะลองทำสิ่งนี้ ถ้ามันทำงานนอก ArcMap ฉันพนันได้เลยว่ามันจะเร็วขึ้น นอกจากนี้ฉันกำลังเรียกใช้ดิสก์ภายในเครื่องแล้วซึ่งเพิ่มความเร็วของสคริปต์เป็นสองเท่า
โคดี้บราวน์

น่าเศร้าที่ Select ไม่ทำงานนอก ArcMap และจำเป็นเพราะฉันต้องทำรูปร่างเป็นตารางตามรูปร่าง
โคดี้บราวน์

3
@ CodyBrown- คุณไม่ถูกต้องเกี่ยวกับการเลือกไม่ทำงานนอกเซสชัน ArcMap ดูคำตอบของฉันเกี่ยวกับการใช้เครื่องมือ MakeFeatureLayer
RyanDalton

ไรอันพูดถูก เมื่อใช้เครื่องมือเลือกด้วยตนเองเครื่องมือนี้จะสร้างมุมมองตารางของข้อมูลอวกาศหรือข้อมูลตารางของคุณ เมื่อใช้มันใน ModelBuilde หรือในสคริปต์คุณต้องสร้างมุมมองและในกรณีของคุณสร้างมันโดยใช้เครื่องมือ MakeFeatureLayer
dchaboya

6

นี้อาจจะไม่ตอบคำถามของคุณสำหรับการเรียกใช้เครื่องมือ ArcPy ภายใน ArcMap แต่เมื่อฉันต้องทำการประมวลผลเนื้อบางกับเครื่องมือทางภูมิศาสตร์ในการประมวลผลและ Python ฉันมักจะเรียกมันนอกระบบ GIS โดยใช้ IDE PyScripter ฉันพบว่ามันทำงานได้เร็วขึ้น ฉันยังใช้ RAMDISK สำหรับชุดข้อมูลเอาต์พุตขนาดเล็กชั่วคราว (เช่นพื้นที่ทำงานin_memory )

นี่เป็นเคล็ดลับยอดนิยมของฉัน! :)


2
เพื่อทำให้คำตอบนี้ค่อนข้างยุ่งเหยิงเมื่อเรียกใช้สคริปต์จาก Python IDE หลาย ๆ ตัวจะฉีดฟังก์ชั่นการติดตามกลับเพื่อช่วยในการดูตัวแปรและความช่วยเหลือในการดีบักอื่น ๆ ฟังก์ชั่นนี้สามารถทำให้สคริปต์ทำงานช้าลงอย่างมากถ้ามันทำมากเกินไปเมื่อมันถูกเรียกว่า ALL THE TIME และบางครั้งมันก็ถูกติดตั้งโดยปริยายโดยที่ผู้ใช้ไม่ต้องทำอะไรเลย มีกรณีทางพยาธิวิทยาบางอย่างที่ฉันสังเกตเห็นว่าสคริปต์ Python ทำงานใน ArcMap ทำงานใน 4 นาทีในขณะที่สคริปต์เดียวกันจาก Wing IDE ใช้เวลา 3 ชั่วโมง ทันทีที่มันถูกเรียกใช้จาก Python.exe โดยไม่มี Wing มันก็กลับไปที่พื้นที่รันไทม์ประมาณ 2-3 นาที
Jason Scheirer

1
ฉันมีอาการปวดหัวในการปรับสคริปต์ของฉันบน ArMap บางครั้งฉันไม่สามารถสมบูรณ์ได้จนกว่าฉันจะหันไป Pyscripter มันสามารถลดเวลาในการดำเนินการเมื่อเทียบกับ Arcmap โดยไม่ต้องใช้เคล็ดลับการเพิ่มประสิทธิภาพใด ๆ
geogeek

@ JasonScheirer คุณคิดว่า Tweak ใน Wing ปิดลงไหม? ฉันแน่ใจว่ามี
เคอร์ติสราคา

5

ลองแสดงความคิดเห็นกับ arcpy.SetProgressorLabel และดูว่าคุณเร่งความเร็วมากแค่ไหน ฉันพบว่าการแสดงผลหน้าจอใด ๆ กลับไปสู่ความงุนงงของ DOS ทำให้การประมวลผลช้าลงอย่างมาก หากคุณต้องการเห็นผลลัพธ์นั้นจริงๆให้ลองแสดงมันทุกวงที่ Nth


4

ตรวจสอบให้แน่ใจว่าคุณลบimport xxxxบรรทัดที่ไม่ได้ใช้

(เช่นถ้าคุณไม่ได้ใช้ฟังก์ชั่นทางคณิตศาสตร์ใด ๆ เลยคุณอาจต้องimport Mathใช้เวลาในการโหลดสคริปต์)

แม้ว่าสิ่งนี้จะไม่ส่งผลกระทบอย่างใหญ่หลวงต่อสคริปต์เดี่ยวที่ทำงาน (เช่นของคุณ) แต่จะมีผลกับสคริปต์ใด ๆ ที่ทำงานเป็นประจำและซ้ำ ๆ


7
ฉันสงสัยว่าโมดูล Python มาตรฐานใดต้องใช้เวลามากกว่าหนึ่งในพันที่ใช้โมดูล arcpy เพื่อเริ่มต้น
blah238

1
@ blah238 import Mathอาจเป็นตัวอย่างที่ไม่ดี อย่างไรก็ตามไลบรารี ArcPy ที่ใหญ่กว่าบางแห่งใช้เวลาในการโหลดนานพอสมควร
nagytech

1
นี้ยังคงโกนออกเพียงไม่กี่วินาที (มากที่สุด!) ไม่ใช่ชั่วโมง
ไมค์ T

1
@MikeToews สำหรับสคริปต์ที่ทำงานบ่อยครั้งและซ้ำ ๆ กันไม่กี่วินาทีก็เพิ่มขึ้นในช่วงไม่กี่วัน / สัปดาห์เป็นต้นแม้ว่าสิ่งนี้จะไม่สามารถแก้ปัญหาหลักของ OP ได้ แต่เขาก็ขอคำแนะนำทั่วไป
nagytech
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.