Python + minGW

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Natürlich tut der das. Weil er Informationen sammelt, die man danach auswertet um rauszufinden, wo man bottle necks hat.
drankaner
User
Beiträge: 13
Registriert: Freitag 27. Oktober 2017, 13:22

drankaner hat geschrieben:@sirius3: Ich habe etwa drei Zeitfresser:
1. sind die Matrixmultiplikationen von oben ca. 40%,
2. Ist die Umrechnung in Kamerakoordinaten oben: calculatePointInCameraCoordSys.py diese benötigt etwa 35% der Zeit und
3. ist die Berechnung der möglichen Camerasettings (Also welche Kamera können mir zudem Punkt überhaupt einen Anteil liefern) ca 15%.

Die letzte Funktion hatte ich noch nicht gepostet.

Code: Alles auswählen

def combinations(objects, k):
    if objects == [] or len(objects) < k or k == 0:
	yield []
    elif len(objects) == k:
        yield objects
    else:
        for combination in combinations(objects[1:], k-1):
            yield [objects[0]] + combination
        for combination in combinations(objects[1:], k):
            yield combination

def Cameraset(validCams,validCamsNo,Cams):
        invalidCams=[]
    
        combs=list(combinations([0,1,2,3,4,5,6,7],validCamsNo))
        #int(math.factorial(Cams)/(math.factorial(Cams-validCamsNo)*math.factorial(validCamsNo)))
        for x in range(0,len(validCams)):
            if validCams[x]==0:
                invalidCams.append(x)
        for y in range(0,len(invalidCams)):
            i=0
            possible=len(combs)
            for x in range(0,possible):
                if combs[x-i].count(invalidCams[y])>0:
                    combs.pop(x-i)
                    i+=1
        return combs
Wobei diese, auch denk geringsten Zeitaufwand hat.
Das ganze konnte ich nun doch nochmal effizienter machen, sodass ich hier nun keine Zeit mehr verschwende. Nun ist die Zeitaufteilung wiefolgt:
  • 1. sind die Matrixmultiplikationen von oben ca. 50%,
    2. Ist die Umrechnung in Kamerakoordinaten oben: calculatePointInCameraCoordSys.py diese benötigt etwa 45% der Zeit
Bei nun noch etwa 16 Minuten.

Dann werd eich jetzt mal den Profiler duchlaufen lassen.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@drankaner: wie sieht denn jetzt Dein Code aus, und welche Zeilen brauchen wie lange?

»combinations« gibt es schon fertig in itertools, das braucht man nicht selbst zu schreiben. »Cameraset« und alle Variablennamen halten sich immer noch nicht an die üblichen Konventionen. Funktionen sollten nach einer Tätigkeit benannt sein. `Cams` wird gar nicht verwendet. Man iteriert direkt über Listen und baut sich neue, statt mit pop irgendwie die Liste zu verändern; das versteht nämlich niemand.

Nachdem ich raten konnte, was die unterschiedlichen Parameter bedeuten, kommt das dabei raus:

Code: Alles auswählen

def find_cameraset_with_only_valid_cameras(cameras_validity, set_size):
    combs = list(combinations(range(len(cameras_validity), set_size))
    for num, valid in enumerate(cameras_validity):
        if not valid:
            combs = [c for c in combs if c.count(num) == 0]
    return combs
wobei man sich dann fragen muß, warum Du erst die Kombinationen aller Kameras erzeugst, um dann aus allen Kombinationen die ungültigen wieder zu entfernen und nicht gleich nur aus den Gültigen die Kombinationen erzeugst:

Code: Alles auswählen

def find_cameraset_with_only_valid_cameras(cameras_validity, set_size):
    valid_cameras = [num for num, valid in enumerate(cameras_validity) if valid]
    return list(combinations(valid_cameras, set_size))
drankaner
User
Beiträge: 13
Registriert: Freitag 27. Oktober 2017, 13:22

Sirius3 hat geschrieben:@drankaner: wie sieht denn jetzt Dein Code aus, und welche Zeilen brauchen wie lange?

»combinations« gibt es schon fertig in itertools, das braucht man nicht selbst zu schreiben. »Cameraset« und alle Variablennamen halten sich immer noch nicht an die üblichen Konventionen. Funktionen sollten nach einer Tätigkeit benannt sein. `Cams` wird gar nicht verwendet. Man iteriert direkt über Listen und baut sich neue, statt mit pop irgendwie die Liste zu verändern; das versteht nämlich niemand.
Genau an dem Punkt habe ich angegriffen und den Quatsch mit "pop" wieder rausgeschmissen. Hier muss ich auch gestehen, dass die Funktion erstmal Blind geschrieben habe (Hauptsache es funktioniert).

Code: Alles auswählen

def find_valid_Cameraset(validCams,validCamsNo):
      return list(combinations(validCams,validCamsNo))
Die Zeiten genau Untersuche ich jetzt nochmal genau. Bisher habe ich nur die Zeit für die gesamte Funktion.
8 Minuten für solveTriangulationLGS.py und 6-7 Minuten für calculatePointInCameraCoordSys.py.
drankaner
User
Beiträge: 13
Registriert: Freitag 27. Oktober 2017, 13:22

Das die Variablen nicht der Konvention entsprechen, da stimme ich dir volkommen zu. Allerdings habe ich diese aus unserem tatsächlichen Programm das in C++ besteht (nicht von mir) übernommen und um später einfacher Sachen in dieses zu übernehmen habe diese bestehen lassen.

Nun ja mein
Sirius3 hat geschrieben:@drankaner: statt numpy.full nimmt man numpy.zeros. Welches Format haben denn local_cs_in_global_vector und local_tRefk_vector?
Ist x_iCamNo nicht einfach die Länge der Vektoren? Das braucht man dann nicht extra angeben.
Die ganzen asarray-Aufrufe sind in Deinem Fall überflüssig. Die Klammern bei den if und alle Strichpunkte sind das auch. Die einbuchstabigen Namen sind allesamt schlecht, weil sie nichts aussagen, für was sie stehen.

Die erste Hälfte ist vor allem mit dem `break` etwas seltsam, kann man aber bestimmt genauso zusammenfassen wie die zweite Hälfte, so dass es keine for-Schleifen mehr gibt:

Code: Alles auswählen

    s = x_pPoint3d - o
    s2 = (s**2).sum(axis=1)
    local = (r*s).sum(axis=1)
    local = s2 - local**2 * r2r
    maxsquaredist = local.max()
    meansquaredist = local.mean()
    return x_pPoint3d, maxsquaredist, meansquaredist
Ich habe den Code jetzt so angepasst.

local_cs_in_global_vector übergibt einen Vektor der so aussehen kann:
[array([ 0.06999708, 0.68877751, -0.72814772]), array([ 0.68212451, 0.08660196, -0.7334991 ])] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)

local_tRefk_vector übergibt einen solchen Vektor:
[[1.45608435, -220.028403, 264.029949], [-219.686839, 0.265470325, 264.474263]] (Je nach Anzahl der Kameras, kommt jeweils noch eine Zeile hinzu)

Und x_iCamNo die Anzahl der gültigen Kameras.

Ich habe auch schon einmal anngepasst das local_cs_in_global_vector und local_tRefk_vector jeweils im richtigen Format ankommen, sodass ich numpy.asarray nicht benötige, daraufhin bin ich aber direkt langsamer geworden und zwar deutlich. (Finde ich unlogisch, war aber tatsächlich so)

Code: Alles auswählen

def solverTriangulationLGS(local_cs_in_global_vector, local_tRefk_vector,x_iCamNo):

    a=numpy.zeros((3,3))
    o=numpy.asarray(local_tRefk_vector)
    r=numpy.asarray(local_cs_in_global_vector)

    a[0,0]=x_iCamNo
    a[1,1]=x_iCamNo

    ###Vorbereitung 3D Punkt
    #r2r = Ein einzelner Wert, je Kamera existiert einer!     
    r2r=1/(r**2).sum(axis=1)
    #local = Ein einzelner Wert, je Kamera existiert einer! 
    local=(r*o).sum(axis=1)
    #r_2r = Ein 3er Vector, je Kamera existiert einer! 
    r_r2=(r.transpose()*r2r).transpose()
    #b= ein 3er Vector
    b = (o-(r_r2.transpose()*local).transpose()).sum(axis=0)
    #a=eine 3x3 Matrix
    a-=numpy.tensordot(r, r_r2, axes=[0,0])

    a[2][2] = x_iCamNo * 2 - a[0][0] - a[1][1];

   ###3D Punkt berechnen

    x_pPoint3d = numpy.matmul(numpy.linalg.inv(a),(b))

    ###Validierung des 3D Punkts
    #s = Ein 3er Vector, je Kamera existiert einer! 
    s=x_pPoint3d-o
    #s2 = Ein einzelner Wert, je Kamera existiert einer! 
    s2 = (s**2).sum(axis=1)
    #local = Ein einzelner Wert, je Kamera existiert einer! 
    local = (r*s).sum(axis=1)
    local = s2 - local*(local * r2r); 

    maxsquaredist=local.max()
    sumsquaredist=local.mean()

    return x_pPoint3d,maxsquaredist, sumsquaredist
@kbr: Folgendes kommt beim cProfiler raus (Ich habe mal nur die größten Punkte rausgenommen, aber anfangen kann ich damit nichts wirklich :/):

Code: Alles auswählen

1	          252,125	252,125	1309,809	1309,809	trangulation_batch.py:17(triangulation_batch)					
35383040	  81,419	0	        81,419	0		{built-in	method	numpy.core.multiarray.array}			
24840580	  79,705	0	        79,705	0		{method	'reduce'	of	'numpy.ufunc'	objects}	
17639767	  64,23	0	        64,23	0		{built-in	method	numpy.core.multiarray.matmul}			
35486513	  26,408	0	        26,408	0		{built-in	method	numpy.core.multiarray.zeros}			
17743255	  14,453	0	        78,978	0		{method	'sum'	of	'numpy.ndarray'	objects}	
58992005	  10,06	0	        10,06	0		{built-in	method	time.time}			
10645953	  9,351	0	        9,351	0		{method	'reshape'	of	'numpy.ndarray'	objects}	
21291906	  9,039	0	        9,039	0		{method	'transpose'	of	'numpy.ndarray'	objects}	
3548656	  8,684	0	        8,684	0		{method	'astype'	of	'numpy.ndarray'	objects}	
3548651	  7,597	0	        7,597	0		{built-in	method	numpy.core.multiarray.dot}			
13086729	  6,978	0	        6,978	0		{built-in	method	numpy.core.multiarray.may_share_memory}			
16637016	  4,4	        0	        4,4	        0		{built-in	method	builtins.hasattr}			
28632953	  3,764	0	        3,764	0		{method	'append'	of	'list'	objects}	
3548651	  2,383	0	        51,048	0		{method	'mean'	of	'numpy.ndarray'	objects}	
7170593	  2,278	0	        2,283	0		{built-in	method	builtins.isinstance}			
3548723	  2,261	0	        2,261	0		{built-in	method	builtins.max}			
3548652	  2,146	0	        14,725	0		{method	'max'	of	'numpy.ndarray'	objects}	
3551510	  1,268	0	        1,268	0		{built-in	method	builtins.iter}			
3551908	  1,169	0	        1,169	0		{built-in	method	builtins.getattr}			
3548733	  1,09	0	        1,09	        0		{built-in	method	builtins.min}			
3549617	  1,039	0	        1,04	        0		{method	'get'	of	'dict'	objects}	
3548651	  0,785	0	        0,785	0		{method	'__array_prepare__'	of	'numpy.ndarray'	objects}	

Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@drankaner: 35Mio Aufrufe dauern 81 Sekunden, die könnte man wahrscheinlich sparen, wenn man immer mit Numpy-Arrays arbeitet. Eine Liste von Arrays sieht daher komisch aus. Was dann aber nicht sein sollte, sind die vielen appends, die man nicht mit Numpy-Arrays machen sollte.
Dass Du solverTriangulationLGS 3,5Mio mal aufrufst, hast Du aber nicht gesagt, und in Deinem Profiler-Output fehlen auch alle Zeilen mit Deinen Python-Funktionen. Also bei dem Stückwerk und den ganzen Dingen, die Du verheimlichst, kann man Dir wirklich nicht helfen.
Antworten