2016-11-17 8 views
1

Я пытаюсь использовать модуль python fbx из autodesk, но, похоже, я не могу выполнить ни одну операцию. Это похоже на то, что GIL не перестал. Кто-нибудь нашел ту же проблему, или я делаю что-то неправильно? Когда я говорю, что это не работает, я имею в виду, что код не освобождает поток, и я не могу ничего делать, пока работает код fbx.Autodesk's Fbx Python и threading

Существует не так много кода для публикации, просто чтобы узнать, не случилось ли с кем-нибудь попробовать.

Update:

вот пример кода, пожалуйста, обратите внимание, каждый файл FBX что-то вроде 2 Гб

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

Просьба также поделиться кодом, который не выпускает нить. Вы получите лучший ответ. Прямо сейчас у нас даже не будет представления о том, что вы делаете или пытаетесь достичь. –

+0

Интерпретатор фактически никогда не выполняет одновременно код Python из-за GIL. GIL обычно выпускается только при выполнении ввода-вывода, и текущий поток ожидает его завершения. Пока это происходит, для любых ожидающих потоков будет предоставлена ​​возможность запуска. Таким образом, ваша проблема может не иметь никакого отношения к тому факту, что вы используете модуль fbx. – martineau

+0

@MoinuddinQuadri, код примера загружен. – hdd

ответ

0

Одна проблема, которую я вижу с вашей traverse() функции. Это вызывает себя рекурсивно потенциально огромное количество раз. В другом случае есть все материалы для печати нитей одновременно. Для этого требуется согласование доступа к общему устройству вывода (т. Е. К экрану). Простым способом сделать это является создание и использование глобального объекта threading.Lock.

Сначала нужно создать глобальную Lock, чтобы предотвратить нити из печати в то же время:

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

Затем сделайте нерекурсивную версию traverse(), которая использует его:

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() 

Это не для меня ясно, точно там, где происходит чтение каждого файла fbx. Если все это происходит в результате вызова importer.Import(scene), то это единственный случай, когда любому другому потоку будет предоставлена ​​возможность запуска - если некоторые операции ввода/вывода не выполняются также в функции traverse().

Поскольку печать является, безусловно, формой выхода, переключение потоков также будет иметь место, когда это будет сделано. Однако, если бы вся эта функция выполнялась, выполнялись какие-то вычисления, во время ее выполнения в ней не было бы многопоточности.

Как только вы получаете работу с несколькими чтениями, вы можете столкнуться с недостаточными проблемами памяти, если несколько файлов fbxfib 2GB считываются в память одновременно различными различными потоками.

+0

Привет, печатает как только представитель, конечный результат должен храниться где-то в памяти и сообщаться через ui (qt). Пробовал всевозможные вещи, чтобы сделать эту работу, но, похоже, не работает должным образом (не пробовал блокировки, так как не происходит O (ввода-вывода)). Хорошая точка памяти. нужно добраться до среднего размера fbx, чтобы попробовать (~ 400/600Mb), или моя машина взрывается. Cheers. – hdd

+0

Если нет ввода-вывода, тогда нет возможности для многопоточности. Независимо от того, что вам, вероятно, нужно использовать нерекурсивную версию 'traverse()', потому что каждый вложенный вызов сам по себе использует память, а Python имеет максимальную глубину рекурсии.Если это превышено, это вызовет «RuntimeError». Кроме того, если конечный результат сохраняется в памяти, вам потребуется какой-то способ контролировать параллельный доступ к нему из нескольких потоков (при условии, что у вас есть код, который будет делать некоторые I или O и выпустить GIL, чтобы другие потоки могли запускаться). – martineau

+0

Просто подумал об этом: если ваша функция потока не выполняет никаких операций ввода-вывода, вы можете заставить ее временно отпустить GIL, тем самым предоставив другим потокам возможность запускать, периодически вызывая 'time.sleep()' in цикл в 'traverse()'. – martineau