2016-11-17 44 views
1

Ich versuche, das FBX-Python-Modul von Autodesk zu verwenden, aber es scheint, ich kann keine Operation fädeln. Dies scheint aufgrund der GIL nicht gelöst zu sein. Hat jemand das gleiche Problem gefunden oder mache ich etwas falsch? Wenn ich sage, dass es nicht funktioniert, meine ich, dass der Code den Thread nicht freigibt und ich nicht in der Lage bin, etwas anderes zu tun, während der fbx-Code läuft.Autodesk Fbx Python und Threading

Es gibt nicht viel Code zum Posten, nur um zu wissen, ob es jemandem passiert ist, es zu versuchen.

Update:

hier ist der Beispielcode, bitte beachten Sie, jede FBX-Datei so etwas wie 2GB ist

import os 
import fbx 
import threading 

file_dir = r'../fbxfiles' 


def parse_fbx(filepath): 
    print '-' * (len(filepath) + 9) 
    print 'parsing:', filepath 

    manager = fbx.FbxManager.Create() 
    importer = fbx.FbxImporter.Create(manager, '') 
    status = importer.Initialize(filepath) 
    if not status: 
     raise IOError() 

    scene = fbx.FbxScene.Create(manager, '') 
    importer.Import(scene) 
    # freeup memory 
    rootNode = scene.GetRootNode() 

    def traverse(node): 
     print node.GetName() 

     for i in range(0, node.GetChildCount()): 
      child = node.GetChild(i) 
      traverse(child) 

    # RUN 
    traverse(rootNode) 
    importer.Destroy() 
    manager.Destroy() 


files = os.listdir(file_dir) 
tt = [] 

for file_ in files: 
    filepath = os.path.join(file_dir, file_) 
    t = threading.Thread(target=parse_fbx, args=(filepath,)) 
    tt.append(t) 
    t.start() 
+0

Bitte teilen Sie auch den Code, der den Thread nicht freigibt. Sie werden eine bessere Antwort bekommen. Im Moment werden wir nicht einmal eine Vorstellung davon haben, was Sie tun oder versuchen zu erreichen. –

+0

Der Interpreter führt aufgrund der GIL niemals Python-Code gleichzeitig aus. Die GIL wird im Allgemeinen nur freigegeben, wenn E/A stattfindet und der aktuelle Thread darauf wartet, dass sie abgeschlossen wird. Währenddessen wird allen wartenden Threads eine Chance zum Laufen gegeben. Ihr Problem kann also nichts mit der Tatsache zu tun haben, dass Sie das fbx-Modul verwenden. – martineau

+0

@MoinuddinQuadri, Beispielcode wurde hochgeladen. – hdd

Antwort

0

Ein Problem, das ich mit Ihrer traverse() Funktion sehen ist. Es nennt sich rekursiv potenziell sehr oft. Ein weiterer Grund ist, dass alle Threads gleichzeitig drucken. Um dies richtig zu machen, muss der Zugriff auf das gemeinsame Ausgabegerät (d. H. Den Bildschirm) koordiniert werden. Eine einfache Möglichkeit besteht darin, ein globales Objekt threading.Lock zu erstellen und zu verwenden.

zunächst ein globales Lock erstellen, um Fäden zu verhindern bei gleichzeitig vom Druck:

file_dir = '../fbxfiles' # an "r" prefix needed only when path contains backslashes 
print_lock = threading.Lock() # add this here 

Dann eine nicht-rekursive Version von traverse() machen, die es verwendet:

def traverse(rootNode): 
     with print_lock: 
      print rootNode.GetName() 

     for i in range(node.GetChildCount()): 
      child = node.GetChild(i) 
      with print_lock: 
       print child.GetName() 

Es mir nicht klar ist, genau dort, wo das Lesen jeder fbx-Datei stattfindet. Wenn alles als Ergebnis des Aufrufs importer.Import(scene) passiert, dann ist es das einzige Mal, dass anderen Threads eine Chance zum Ausführen gegeben wird - es sei denn, einige E/A sind auch innerhalb der traverse() Funktion ausgeführt.

Da das Drucken definitiv eine Form der Ausgabe ist, kann die Thread-Umschaltung auch erfolgen, wenn es fertig ist. Wenn jedoch die gesamte Funktion Berechnungen irgendeiner Art ausführt, findet während ihrer Ausführung kein Multithreading statt.

Sobald die Multi-Lese-Funktion aktiviert ist, können Speicherprobleme auftreten, wenn mehrere 2 GB fbx-Dateien gleichzeitig von den verschiedenen Threads in den Speicher gelesen werden.

+0

Hallo, Drucke wie sind nur repräsentativ, das Endergebnis sollte irgendwo im Speicher gehalten werden und durch eine UI (qt) gemeldet werden. Versucht alle möglichen Dinge, um dies zu erreichen, aber es scheint nicht zu funktionieren wie erwartet (Locks wurden nicht versucht, da kein O (von I/O) passiert). Guter Punkt auf dem Speicher obwohl. müssen zu einem mittleren fbx zu versuchen (~ 400/600Mb) oder meine Maschine explodiert. Prost. – hdd

+0

Wenn keine E/A vorhanden ist, besteht keine Möglichkeit für das Multithreading. Unabhängig davon müssen Sie wahrscheinlich eine nicht-rekursive Version von 'traverse()' verwenden, da jeder verschachtelte Aufruf an sich Speicherplatz verbraucht und Python eine maximale Rekursionstiefe erlaubt.Wenn das überschritten wird, wird ein 'RuntimeError' verursacht. Wenn das Endergebnis im Speicher bleibt, benötigen Sie eine Möglichkeit, den gleichzeitigen Zugriff von mehreren Threads darauf zu steuern (vorausgesetzt, Sie hatten Code, der einige I- oder O-Operationen ausführen und die GIL freigeben würde, damit andere Threads ausgeführt werden könnten). – martineau

+0

Nur an diesen Ansatz gedacht: Wenn Ihre Thread-Funktion keine E/A ausführt, können Sie die GIL vorübergehend freigeben, wodurch anderen Threads die Möglichkeit zum Ausführen gegeben wird, indem Sie 'time.sleep()' regelmäßig aufrufen die Schleife in 'traverse()'. – martineau