Massimizzare l'uso della CPU


9

La mia sceneggiatura interseca le linee con i poligoni. È un processo lungo poiché ci sono più di 3000 linee e più di 500000 poligoni. Ho eseguito da PyScripter:

# Import
import arcpy
import time

# Set envvironment
arcpy.env.workspace = r"E:\DensityMaps\DensityMapsTest1.gdb"
arcpy.env.overwriteOutput = True

# Set timer
from datetime import datetime
startTime = datetime.now()

# Set local variables
inFeatures = [r"E:\DensityMaps\DensityMapsTest.gdb\Grid1km_Clip", "JanuaryLines2"]
outFeatures = "JanuaryLinesIntersect"
outType = "LINE"

# Make lines
arcpy.Intersect_analysis(inFeatures, outFeatures, "", "", outType)

#Print end time
print "Finished "+str(datetime.now() - startTime)


La mia domanda è: c'è un modo per far funzionare la CPU al 100%? Funziona sempre al 25%. Immagino che lo script sarebbe più veloce se il processore fosse al 100%. Indovinare?
La mia macchina è:

  • Standard di Windows Server 2012 R2
  • Processore: CPU Intel Xeon E5-2630 0 a 2,30 GHz 2,29 GHz
  • Memoria installata: 31,6 GB
  • Tipo di sistema: sistema operativo a 64 bit, processore basato su x64


inserisci qui la descrizione dell'immagine


Consiglio vivamente di optare per il multi-threading. Non è banale da configurare, ma compenserà più che altro gli sforzi.
Alok Jha,

1
Che tipo di indice spaziale hai applicato ai tuoi poligoni?
Kirk Kuykendall,

1
Inoltre, hai provato la stessa operazione con ArcGIS Pro? È a 64 bit e supporta il multithread. Sarei sorpreso se fosse abbastanza intelligente da spezzare un Intersect in più thread, ma vale la pena provare.
Kirk Kuykendall,

La classe di caratteristiche poligono ha un indice spaziale chiamato FDO_Shape. Non ci ho pensato. Dovrei crearne un altro? Non è abbastanza?
Manuel Frias,

1
Dato che hai molta RAM ... hai provato a copiare i poligoni in una featureclass in memoria e poi a intersecare le linee con quello? O se tenendolo su disco, hai provato a compattarlo? Presumibilmente la compattazione migliora l'I / O.
Kirk Kuykendall,

Risposte:


13

Fammi indovinare: la tua CPU ha 4 core, quindi il 25% di utilizzo della CPU, è il 100% di utilizzo di un core e 3 core inattivi.

Quindi l'unica soluzione è rendere il codice multi-thread, ma non è un compito semplice.


4
La CPU che menziona utilizza 6 core e 12 thread.
Kersten,

5
Ciao, non posso sottovalutare, ma mi piacerebbe farlo! Python ha purtroppo un GIL, quindi non puoi affatto eseguire il multithreading (la cosa migliore che puoi fare è avere il GIL sbloccato quando un thread si blocca su un syscall)
Alec Teal

2
@AlecTeal sicuramente puoi, ad esempio con Jython o il multiprocessingmodulo.
destra

@elyse dicendo "Oh sì, puoi farlo totalmente in Python, se per Python intendi Jython" non conta. Dovrei esaminare il multiprocessing, un'importazione avrebbe il potere di reimplementare ciò che rende Python Python?
Alec Teal,

@AlecTeal Genera processi (che sono un modo per fare parallelismo). Vedi la documentazione del multiprocessingmodulo.
destra

13

Non sono così sicuro che si tratti di un'attività legata alla CPU. Penserei che sarebbe un'operazione legata all'I / O, quindi cercherei di usare il disco più veloce a cui ho avuto accesso.

Se E: è un'unità di rete, l'eliminazione sarebbe il primo passo. Se non è un disco ad alte prestazioni (ricerca <7ms), sarebbe il secondo. È possibile ottenere alcuni benefici dalla copia del layer poligonale in un'area di in_memorylavoro, ma il vantaggio potrebbe dipendere dalla dimensione della classe di feature poligono e dall'utilizzo dell'elaborazione in background a 64 bit.

L'ottimizzazione del throughput I / O è spesso fondamentale per le prestazioni GIS, quindi ti consiglio di prestare meno attenzione al misuratore della CPU e maggiore attenzione alla rete e ai misuratori del disco.


4

Ho avuto problemi simili di prestazioni per quanto riguarda gli script arcpy, il principale collo di bottiglia non è CPU ma il disco rigido, se stai usando i dati dalla rete che è lo scenario peggiore, prova a spostare i tuoi dati sull'unità SSD, quindi avvia lo script dalla riga di comando non da pyscripter, pyscripter è leggermente più lento, forse perché contiene alcune cose di debug, se non sei soddisfatto di nuovo, pensa a mettere in parallelo lo script, perché ogni thread di Python prende un core CPU, la tua CPU ha 6 core, quindi puoi avviarlo 6 script contemporaneamente.


3

Dato che stai usando Python e come suggerito sopra, considera l'utilizzo del multiprocessing se il tuo problema può essere eseguito in parallelo.

Ho scritto un piccolo articolo sul sito Web di Geonet sulla conversione di uno script Python in uno strumento di script Python che potrebbe essere utilizzato all'interno di Modelbuilder. Il documento elenca il codice e descrive alcune insidie ​​per eseguirlo come uno strumento di script. Questo è solo un posto dove iniziare a cercare:

https://geonet.esri.com/docs/DOC-3824


Questa sembra la strada da percorrere! Il tuo script funziona bene ma non so come modificarlo per farlo funzionare con il mio script. Meglio, stavo pensando di fare un'intersezione tabulare con poligoni e linee. Qualche idea?
Manuel Frias,

3

Come detto prima, dovresti usare il multiprocessing o il threading . Ma ecco che arriva un avvertimento: il problema deve essere divisibile! Dai un'occhiata a https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms .

Se il tuo problema è divisibile, potresti procedere come segue:

  • Creare una coda in cui archiviare i dati di input per i processi / thread
  • Creare una coda in cui sono archiviati i risultati
  • Crea una funzione o una classe che può essere utilizzata come processo / thread che risolve il nostro problema

Ma come ha detto geogeek, potrebbe non essere un problema di limitazione della CPU, ma di IO. Se hai abbastanza RAM puoi precaricare tutti i dati e quindi elaborarli, il che ha il vantaggio che i dati possono essere letti in una volta sola, quindi non interrompe sempre il processo di calcolo.


3

Ho deciso di provarlo usando 21513 linee e 498596 poligoni. Ho testato l'approccio multiprocessore (12 processori sulla mia macchina) usando questo script:

import arcpy,os
import multiprocessing
import time
t0 = time.time()
arcpy.env.overwriteOutput = True
nProcessors=4
folder=r'd:\scratch'

def function(inputs):
        nGroup=inputs[0]
        pGons=inputs[1]
        lines=inputs[2]
        outFeatures = '%s%s%s_%i.shp' %(folder,os.sep,'inters',nGroup)
        fids= tuple([i for i in range(nGroup,500000,nProcessors-1)])
        lyr='layer%s'%nGroup
        query='"FID" in %s' %str(fids)
        arcpy.MakeFeatureLayer_management(pGons,lyr,query)
        arcpy.Intersect_analysis([lines,lyr], outFeatures)
        return outFeatures
if __name__ == "__main__":
        inPgons='%s%s%s' %(folder,os.sep,'parcels.shp')
        inLines='%s%s%s' %(folder,os.sep,'roads.shp')
        m,bList=0,[]
        for i in range(nProcessors):
                bList.append([i,inPgons,inLines])
        pool = multiprocessing.Pool(nProcessors-1)
        listik=pool.map(function, bList)
##      apply merge here
        print listik
        print ('%i seconds' %(time.time()-t0))

Risultati, secondi:

  • disco rigido locale normale - 191
  • unità locale superveloce - 220
  • unità di rete - 252

La cosa divertente ci sono voluti solo 87 secondi usando lo strumento di geoprocessing da mxd. Forse qualcosa di sbagliato nel mio approccio al pool ...

Come si può vedere, ho usato una query FID piuttosto brutta in (0, 4, 8,12 ... 500000) per rendere divisibile l'attività.

È possibile che la query basata su un campo precalcolato, ad esempio CFIELD = 0, riduca notevolmente il tempo.

Ho anche scoperto che il tempo riportato dagli strumenti multiprocessore può variare molto.


1
Sì, stai usando un elenco, che presenta problemi di blocco. Prova un multiprocessing.queue. Cerca anche di non scrivere elementi nei processi di lavoro, ma crea una coda di uscita con i dati che vuoi scrivere e lascia che ciò avvenga tramite un processo di scrittura.
Benjamin,

3

Non ho familiarità con PyScripter, ma se è supportato da CPython, dovresti optare per il multiprocessing e non il multi-threading fino a quando il problema stesso è divisibile (come altri già menzionato).

CPython ha un Global Interpreter Lock , che annulla tutti i benefici che più thread potrebbero portare nel tuo caso .

Di sicuro in altri contesti i thread di Python sono utili, ma non nei casi in cui sei associato alla CPU.


1

La mia domanda è: c'è un modo per far funzionare la CPU al 100%

Poiché la tua CPU ha più core, massimizzerai solo il core su cui è in esecuzione il tuo processo. A seconda di come hai configurato il tuo chip Xeon, funzionerà fino a 12 core (6 fisici e 6 virtuali con hyperthreading attivo). Anche ArcGIS a 64 bit non è in grado di trarne vantaggio, e ciò può comportare limitazioni della CPU quando il processo a thread singolo massimizza il core su cui è in esecuzione. È necessaria un'applicazione multi-thread per distribuire il carico sui core OPPURE (molto più semplicemente) è possibile ridurre il numero di core in esecuzione sulla CPU per aumentare la produttività.

Il modo più semplice per fermare la limitazione della CPU (e assicurarsi che sia davvero la limitazione della CPU non le restrizioni di I / O del disco) è quello di modificare le impostazioni del BIOS per Xeon e impostarlo su un enorme singolo core. L'aumento delle prestazioni sarà sostanziale. Ricorda solo che questo compromette considerevolmente le capacità multi-tasking dei tuoi PC, quindi è meglio se hai una macchina di processo dedicata su cui implementare questo. È molto più semplice che provare a eseguire il multithreading del codice, che la maggior parte delle funzioni di ArcGIS Desktop (al 10.3.1) non supporta comunque.


Quale impostazione dovresti cercare per trasformare la tua CPU in "un unico single core"?
Alex McVittie,

1
Il menu esatto dipenderà dal BIOS e dal firmware del chip, ma in genere si trova in Impostazione menu BIOS> Avanzate> Configurazione CPU. Dovrai disattivare l'hyper-threading e quindi impostare il numero di core da attivare. 0 è di solito tutto - impostato su 1 se si desidera un core grande. Buona idea prendere nota delle impostazioni prima di cambiare le cose: sembra ovvio ma facile da trascurare se le cose non dovessero funzionare.
Kingmi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.