Autodesk 的 Fbx Python 和线程

Posted

技术标签:

【中文标题】Autodesk 的 Fbx Python 和线程【英文标题】:Autodesk's Fbx Python and threading 【发布时间】:2017-04-01 08:55:56 【问题描述】:

我正在尝试使用来自 Autodesk 的 fbx python 模块,但似乎我无法执行任何操作。这似乎是由于 GIL 没有发布。有没有人发现同样的问题或者我做错了什么?当我说它不起作用时,我的意思是代码没有释放线程并且我不能做任何其他事情,而 fbx 代码正在运行。

没有太多代码可以发布,只是想知道是否有人尝试过。

更新:

这里是示例代码,请注意每个 fbx 文件大约是 2GB

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

【问题讨论】:

请同时分享代码,不释放线程。你会得到更好的回应。现在,我们甚至不知道您正在做什么或试图实现什么 由于 GIL,解释器实际上永远不会同时执行 Python 代码。 GIL 通常仅在发生 I/O 并且当前线程正在等待它完成时才释放。在此过程中,任何等待的线程都将有机会运行。因此,您的问题可能与您使用 fbx 模块这一事实无关。 @MoinuddinQuadri,示例代码已上传。 @martineau,谢谢,请看一下我发布的代码。 【参考方案1】:

我看到的一个问题是您的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()

我不清楚读取每个 fbxfile 的确切位置。如果这一切都是由于importer.Import(scene) 调用而发生的,那么这是任何其他线程唯一有机会运行的时间——除非在traverse() 函数中[也] 完成了某些I/O。

由于打印绝对是一种输出形式,因此完成后也可以进行线程切换。但是,如果函数所做的只是执行某种类型的计算,那么在执行过程中不会发生多线程。

一旦你让多重读取工作,如果多个 2GB fbxfiles 被多个不同的线程同时读取到内存中,你可能会遇到内存不足的问题。

【讨论】:

嗨,打印只是代表,最终结果应该保存在内存中的某个地方并通过 ui (qt) 报告。尝试了各种方法来完成这项工作,但似乎没有按预期工作(没有尝试锁定,因为没有 O(I/O)发生)。不过关于内存的好点。需要使用中型 fbx 来尝试(~400/600Mb),否则我的机器会爆炸。干杯。 如果没有 I/O,那么就没有机会发生多线程。无论如何,您可能需要使用traverse() 的非递归版本,因为对自身的每个嵌套调用都会占用内存,并且 Python 具有允许的最大递归深度。如果超过,将导致RuntimeError。此外,如果最终结果保存在内存中,您将需要某种方法来控制从多个线程对它的并发访问(假设您的代码会执行一些 I 或 O 并释放 GIL 以便其他线程可以运行)。 刚想到这个办法:如果你的线程函数不做任何I/O,你可以强制它暂时释放GIL,从而给其他线程运行的机会,调用@987654331 @ 周期性地在traverse() 的循环内。

以上是关于Autodesk 的 Fbx Python 和线程的主要内容,如果未能解决你的问题,请参考以下文章

fbx sdk 支持ios android吗

Autodesk forge 中 FBX 扩展中的 3D 模型纹理不可见

Autodesk Maya fbx 文件导出

MATLAB读取fbx文件

创建基于 fbx sdk 的 c++ 项目

创建基于 fbx sdk 的 c++ 项目