問題描述
我對 TensorFlow 還很陌生,現在正在研究自定義操作開發.我已經閱讀了官方教程,但我覺得很多事情發生在幕后,我并不總是想將我的自定義操作放在 user_ops 目錄中.
I am fairly new to TensorFlow and right now looking into the custom op development. I have already read the official tutorial but I feel a lot of things happen behind the scenes and I do not always want to put my custom ops in user_ops directory.
因此,我使用了 示例 word2vec
As such, I took up an example word2vec
使用自定義Skipgram"操作,其注冊定義如下:
/word2vec_o??ps.cc
其內核實現在這里:
/word2vec_kernels.cc
which uses a custom "Skipgram" op whose registration is defined here:
/word2vec_ops.cc
and whose kernel implementation is here:
/word2vec_kernels.cc
查看構建文件,我嘗試構建單個目標
Looking at the build file, I tried to build individual targets
1) bazel build -c opt tensorflow/models/embedding:word2vec_o??ps
這會按預期生成一堆目標文件.
1) bazel build -c opt tensorflow/models/embedding:word2vec_ops
This generates bunch of object files as expected.
2) bazel build -c opt tensorflow/models/embedding:word2vec_kernels
同理.
3) bazel build -c opt tensorflow/models/embedding:word2vec_kernels:gen_word2vec
最后一個構建使用自定義規則,即 tf_op_gen_wrapper_py
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tensorflow.bzl#L197-L231
This last build uses a custom rule namely tf_op_gen_wrapper_py
https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tensorflow.bzl#L197-L231
有趣的是,這僅取決于操作注冊,而不取決于內核本身.
Interesting to note that this only depends on Op Registration and not on the kernel itself.
畢竟以上,如果我使用
bazel build -c opt tensorflow/models/embedding:word2vec
它工作正常,但我看不到內核 C++ 代碼鏈接的位置和方式?
it works fine, but I fail to see where and how the kernel c++ code linked?
此外,我還想了解 tf_op_gen_wrapper_py
規則以及 ops 注冊幕后的整個編譯/鏈接過程.
Additionally, I would also like to understand the tf_op_gen_wrapper_py
rule and the whole compilation/linking procedure that goes behind the scenes for ops registration.
謝謝.
推薦答案
When 為 TensorFlow 添加一種新的操作,主要有兩個步驟:
When adding a new kind of operation to TensorFlow, there are two main steps:
注冊op",包括為操作定義一個接口,和
Registering the "op", which involves defining an interface for the operation, and
注冊一個或多個內核",這涉及為操作定義實現,可能具有針對不同數據類型或設備類型(如 CPU 或 GPU)的專門實現.
Registering one or more "kernels", which involves defining implementation(s) for the operation, perhaps with specialized implementations for different data types, or device types (like CPU or GPU).
這兩個步驟都涉及編寫 C++ 代碼.注冊操作使用 REGISTER_OP
宏,注冊內核使用 REGISTER_KERNEL_BUILDER()
宏.這些宏創建靜態初始化程序,在加載包含它們的模塊時運行.op和kernel注冊主要有兩種機制:
Both steps involve writing C++ code.
Registering an op uses the REGISTER_OP()
macro, and registering a kernel uses the REGISTER_KERNEL_BUILDER()
macro. These macros create static initializers that run when the module containing them is loaded. There are two main mechanisms for op and kernel registration:
靜態鏈接到核心 TensorFlow 庫,以及靜態初始化.
Static linking into the core TensorFlow library, and static initialization.
運行時動態鏈接,使用 tf.load_op_library()
函數.
Dynamic linking at runtime, using the tf.load_op_library()
function.
在 "Skipgram"
的情況下,我們使用選項 1(靜態鏈接).操作鏈接到核心 TensorFlow 庫此處內核鏈接在這里.(請注意,這并不理想:word2vec
操作是在我們擁有 tf.load_op_library()
之前創建的,因此沒有動態鏈接它們的機制.)因此首次加載 TensorFlow 時會注冊操作和內核(在 import tensorflow as tf
中).如果它們是今天創建的,它們將被動態加載,這樣它們只會在需要時才被注冊.(SyntaxNet 代碼有一個示例.)
In the case of "Skipgram"
, we use option 1 (static linking). The ops are linked into the core TensorFlow library here, and the kernels are linked in here. (Note that this is not ideal: the word2vec
ops were created before we had tf.load_op_library()
, and so there was no mechanism for linking them dynamically.) Hence the ops and kernels are registered when you first load TensorFlow (in import tensorflow as tf
). If they were created today, they would be dynamically loaded, such that they would only be registered if they were needed. (The SyntaxNet code has an example of dynamic loading.)
tfper_op()op 庫依賴項列表,并為這些操作生成 Python 包裝器.該規則僅取決于 op 注冊的原因是 Python 包裝器完全由 op 的接口決定,該接口在 op 注冊中定義.值得注意的是,Python 接口不知道是否有針對特定類型或設備的專用內核.包裝器生成器將 op 注冊鏈接到 簡單的 C++ 二進制文件/a> 為每個注冊的操作生成 Python 代碼.請注意,如果使用
tf.load_op_library()
,則不需要自己調用包裝器生成器,因為tf.load_op_library()
會在運行時生成必要的代碼.
The tf_op_gen_wrapper_py()
rule in Bazel takes a list of op-library dependencies and generates Python wrappers for those ops. The reason that this rule depends only on the op registration is that the Python wrappers are determined entirely by the interface of the op, which is defined in the op registration. Notably, the Python interface has no idea whether there are specialized kernels for a particular type or device. The wrapper generator links the op registrations into a simple C++ binary that generates Python code for each of the registered ops.
Note that, if you use tf.load_op_library()
, you do not need to invoke the wrapper generator yourself, because tf.load_op_library()
will generate the necessary code at runtime.
這篇關于理解 TensorFlow 中的操作注冊和內核鏈接的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!