在单(多核)CPU 设备上执行 TensorFlow

2024-01-02

我对 TensorFlow 在只有 CPU 设备且网络仅用于推理的特定情况下的执行模型有一些疑问,例如使用图像识别(https://www.tensorflow.org/tutorials/image_recognition https://www.tensorflow.org/tutorials/image_recognition) 具有多核平台的 C++ 示例。

下面,我将尝试总结一下我所理解的内容,同时提出一些问题。

Session->Run()(文件 direct_session.cc)调用 ExecutorState::RynAsynch,它使用根节点初始化 TensorFlow 就绪队列。

然后,指令

runner_([=]() { Process(tagged_node, scheduled_usec); }); (executor.cc, function ScheduleReady, line 2088)

将节点(以及相关操作)分配给 inter_op 池的线程。 但是,我并不完全理解它是如何工作的。 例如,在 ScheduleReady 尝试分配比 inter_op 池大小更多的操作的情况下,操作如何排队?(先进先出顺序?) 池中的每个线程都有一个操作队列还是有一个共享队列? 我在代码中哪里可以找到这个? 在哪里可以找到池中每个线程的主体?

另一个问题是关于 inline_ready 管理的节点。这些(廉价或死亡)节点的执行与其他节点有何不同?

然后,(仍然,据我理解)执行流程从 ExecutorState::Process 继续,执行操作,区分同步和异步操作。 同步和异步操作在执行方面有何不同?

当操作执行时,PropagateOutputs(调用ActivateNodes)将由于当前节点(前驱)的执行而变得就绪的每个后继节点添加到就绪队列中。

最后,NodeDone() 调用 ScheduleReady() 来处理当前 TensorFlow 就绪队列中的节点。

反之,intra_op线程池如何管理取决于具体的内核吧?内核请求的操作是否可能比intra_op线程池大小更多? 如果是,它们按照哪种顺序排队? (先进先出?)

一旦操作被分配给池中的线程,那么它们的调度就会留给底层操作系统,或者 TensorFlow 会强制执行某种调度策略?

我在这里问是因为我在文档中几乎没有找到有关执行模型这部分的任何内容,如果我错过了一些文档,请指出所有文档。


重新线程池:当 Tensorflow 使用 DirectSession 时(正如您的情况),它使用 Eigen 的 ThreadPool。我无法获得 TensorFlow 中使用的 Eigen 官方版本的网络链接,但这里有一个线程池的链接code https://github.com/RLovelett/eigen/blob/ad8fd1bbcf329088f16af5875e4b15c2bce95df1/unsupported/Eigen/CXX11/src/ThreadPool/NonBlockingThreadPool.h。这个线程池正在使用这个队列实现RunQueue https://eigen.tuxfamily.org/dox/unsupported/RunQueue_8h_source.html。每个线程有一个队列。

重新 inline_ready: Executor:Process被调度在一些特征线程中。当它运行时,它会执行一些节点。当这些节点完成后,它们使其他节点(张量流操作)准备就绪。其中一些节点并不昂贵。它们被添加到 inline_ready 并在同一线程中执行,而不产生任何结果。其他节点很昂贵,并且不会在同一线程中“立即”执行。它们的执行是通过 Eigen 线程池来调度的。

重新同步/异步内核:Tensorflow 操作可以由同步(大多数 CPU 内核)或异步内核(大多数 GPU 内核)支持。同步内核在运行的线程中执行Process。异步内核被分派到其设备(通常是 GPU)来执行。当异步内核完成时,它们调用NodeDone method.

关于内部操作线程池:内部操作线程池可供内核并行运行其计算。大多数CPU内核不使用它(GPU内核只是调度到GPU)并在调用该函数的线程中同步运行Compute方法。根据配置的不同,要么有一个由所有设备 (CPU) 共享的内部操作线程池,要么每个设备都有自己的线程池。内核只是在这个线程池上安排它们的工作。这是一个这样的例子kernel https://github.com/tensorflow/tensorflow/blob/0b437ada0654820e21f81bd415f691251408346a/tensorflow/contrib/boosted_trees/kernels/prediction_ops.cc#L271。如果任务多于线程,则它们会按未指定的顺序进行调度和执行。这里是线程池接口 https://github.com/petewarden/tensorflow_makefile/blob/49c08e4d4ff3b6e7d99374dc2fbf8b358150ef9c/tensorflow/core/lib/core/threadpool.h暴露于内核。

我不知道张量流以任何方式影响操作系统线程的调度。您可以要求它进行一些旋转(即不立即将线程交给操作系统)以最大限度地减少延迟(来自操作系统调度),但仅此而已。

这些内部细节没有被故意记录,因为它们可能会发生变化。如果您通过 Python API 使用 TensorFlow,您只需要知道您的操作将在其输入准备就绪时执行。如果您想执行超出此范围的某些命令,您应该使用:

with tf.control_dependencies(<tensors_that_you_want_computed_before_the_ops_inside_this_block>):
  tf.foo_bar(...) 

如果您正在编写自定义 CPU 内核并希望在其中实现并行性(对于非常昂贵的内核通常很少需要),那么您可以依赖上面链接的线程池接口。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在单(多核)CPU 设备上执行 TensorFlow 的相关文章

随机推荐