multicore cpus nutzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bigpappa
User
Beiträge: 7
Registriert: Montag 26. Mai 2008, 15:43

Hallo,

ich habe ein recht rechenintensives programm geschrieben. Nun ist mir aufgefallen das auf multicore plattformen trotz threading nur eine CPU genutzt wird.
Ich habe die berechnung in 4 threads aufgeteilt die ich folgendermaßen aufrufe:

Code: Alles auswählen

        th1 = threading.Thread(target=self.GetPath, args=(0, calls))
        th1.start()
Wie müßte ich das threading implementieren um tatsächlich die performance auszuschöpfen?

Vielen Dank.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Sieh dir mal das an: http://pyprocessing.berlios.de/
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
BlackJack

Alternativ vielleicht auch: http://www.parallelpython.com/

Und Pyro ist auch einen Blick wert.
bigpappa
User
Beiträge: 7
Registriert: Montag 26. Mai 2008, 15:43

ich hab mir parallelpython angeschaut, ich denke das sollte meinen zwecken dienlich sein.
nun möchte ich das allerdings innerhalb einer klasse nutzen.

Code: Alles auswählen

class CreateImportFiles():
    ############################################################################
    # Init
    ############################################################################
    def __init__(self,  parent, 
                 argKonfiguration
                 ):
        
        self.MainApp = parent
        
        self.Konfiguration = argKonfiguration
        self.DebugLevel = 12
        self.IOPoints = []
        self.FreelanceExportPvLst = []

    def CreatePathListAll(self):
        job_server=pp.Server()
        calls=len(self.IOPoints) / 2
        job_server.submit((self.WritePath), (self, 0, calls))
        job_server.submit((self.WritePath), (self, calls, len(self.IOPoints)))

        job_server.wait()

    def WritePath(self, Start, End):
        for k in range(Start, End):
            if self.IOPoints[k][0] == self.FreelanceExportPvLst[0] :
            #hier wird berechnet und einträge in self.IOPoints hinzugefügt und entfernt.


Dabei bekomme ich den Fehler 'TypeError : the sip.wrapper type cannot be instantiated or sub-classed'.
Funktioniert das überhaupt innerhalb einer Klasse? Oder muss ich WritePath in eine eigene Klasse packen? Kann parallelpython innerhalb einer Klasse genutzt werden?

Vielen dank
BlackJack

Wo genau tritt denn der Fehler auf? Kompletter Traceback wäre nicht schlecht.

Grundsätzlich sollte es egal sein von wo man das benutzt.

Vielleicht kannst Du das Beispiel auch soweit reduzieren, dass es möglichst klein aber vollständig ist und immer noch das Problem aufweist.

`CreateImportFiles` ist übrigens ein ungünstiger Name für eine Klasse. Insbesondere wenn man Funktionen nach dem gleichen Muster benennt.
bigpappa
User
Beiträge: 7
Registriert: Montag 26. Mai 2008, 15:43

hallo,
hier eine nachbildung in der python idle,

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

##general import
import pp

class ImportFiles():
    def __init__(self,  parent, 
                 argKonfiguration
                 ):
        
        self.MainApp = parent
        self.DebugLevel=12
        self.Konfiguration = argKonfiguration
        self.PvLst = []
        self.IOLst = []
        
    def create_path_list(self):
        job_server = pp.Server()
        job_server.submit((self.write_path), (self, 0, len(self.IOLst)))
        job_server.wait()

    def write_path(self, start, end):
        print 'writepath'
        for k in range(start, end):
            for Pv in self.PvLst:
                if Pv[0] == self.IOLst[k][0]:
                    print 'extend IO: ' + self.IOLst[k][0]
                    self.IOLst[k].append(Pv[1])

############################################################################
# Local call for testing
############################################################################
if __name__ == "__main__":
    print 'start tc'
    konfig=[12,1,2]
    importedfiles=ImportFiles('none', konfig)
    importedfiles.IOLst = [['IO-Name1','Typ','DescLong', 'DescShort'],
                           ['IO-Name2','Typ','DescLong', 'DescShort'],
                           ['IO-Name3','Typ','DescLong', 'DescShort'],
                           ['IO-Name4','Typ','DescLong', 'DescShort']]
                          
    importedfiles.PvLst = [['IO-Name1', 'Parameter1', 'Parameter2'],
                           ['IO-Name2', 'Parameter1', 'Parameter2'],
                           ['IO-Name3', 'Parameter1', 'Parameter2'],
                           ['IO-Name4', 'Parameter1', 'Parameter2'],
                           ['IO-Name5', 'Parameter1', 'Parameter2']]
    print 'start create_path_list'                          
    importedfiles.create_path_list()
    
    print importedfiles.IOLst
    print 'done tc'
und der traceback dazu:

Code: Alles auswählen

start tc
start create_path_list
Traceback (most recent call last):
  File "C:\Grillo\parallelpython.py", line 49, in <module>
    importedfiles.create_path_list()
  File "C:\Grillo\parallelpython.py", line 20, in create_path_list
    job_server.submit((self.write_path), (self, 0, len(self.IOLst)))
  File "C:\Python25\Lib\site-packages\pp.py", line 395, in submit
    sfunc = self.__dumpsfunc((func,)+depfuncs, modules)
  File "C:\Python25\Lib\site-packages\pp.py", line 582, in __dumpsfunc
    sources = [self.__get_source(func) for func in funcs]
  File "C:\Python25\Lib\site-packages\pp.py", line 660, in __get_source
    sourcelines = inspect.getsourcelines(func)[0]
  File "C:\Python25\lib\inspect.py", line 618, in getsourcelines
    lines, lnum = findsource(object)
  File "C:\Python25\lib\inspect.py", line 494, in findsource
    raise IOError('could not find class definition')
IOError: could not find class definition
BlackJack

Das ist jetzt aber eine andere Fehlermeldung. Und bei mir läuft das Programm problemlos durch.

Kannst Du das mal ohne IDLE probieren?
bigpappa
User
Beiträge: 7
Registriert: Montag 26. Mai 2008, 15:43

stimmt, die erste fehlermeldung erhalte ich in eric, da ist der ablauf aber auch komplexer.
ohne idle läuft der test ohne fehlermeldung durch, aber er tut dennoch nicht was ich erwarte. :?
in write_path sollte self.IOLst eigentlich erweitert werden, und die print anweisungen erhalte ich auch nicht auf der Konsole.
BlackJack

Du führst die Jobs, bzw. den Job ja gar nicht aus. Die `submit()`-Methode liefert ein aufrufbares Objekt, dessen *Aufruf* asynchron ist!

Code: Alles auswählen

    def create_path_list(self): 
        job_server = pp.Server()
        half_length = len(self.IOLst) // 2
        job1 = job_server.submit(self.write_path, (0, half_length))
        job2 = job_server.submit(self.write_path,
                                 (half_length, len(self.IOLst)))
        job1()
        job2()
Allerdings befreit auch `pp` nicht von den üblichen Problemen die beim Verändern von gemeinsamen Datenstrukturen auftreten. Man sollte die parallel ausgeführten Funktionen besser so schreiben, dass sie ein Ergebnis liefern, dass Du dann am Ende zusammen führst. Beispielsweise so:

Code: Alles auswählen

    def create_path_list(self): 
        job_server = pp.Server()
        half_length = len(self.IOLst) // 2
        job1 = job_server.submit(self.write_path, (0, half_length))
        job2 = job_server.submit(self.write_path,
                                 (half_length, len(self.IOLst)))
        self.IOLst = job1() + job2()
Antworten