[英]Bazel targets built against TensorFlow C++ API don't execute factory registration functions
我遇到的問題似乎與此處描述的問題相同: https://chromium.googlesource.com/external/github.com/tensorflow/tensorflow/+/v1.4.0/tensorflow/docs_src/mobile/linking_libs。 md#global-constructor-magic
嘗試從您自己的應用程序調用 TensorFlow 時,您可能遇到的最微妙的問題之一是“沒有為給定的 session 選項注冊的工廠沒有注冊”錯誤。 ... TensorFlow 在很多地方都使用了注冊模式:
class RegisterMul { public: RegisterMul() { global_kernel_registry()->Register(“Mul”, [](){ return new MulKernel() }); } }; RegisterMul g_register_mul;
This sets up a class RegisterMul with a constructor that tells the global kernel registry what function to call when somebody asks it how to create a “Mul” kernel. 然后是 class 的全局 object,因此構造函數應該在任何程序的開頭調用。
定義的全局 object 未被任何其他代碼使用,因此未考慮到這一點設計的鏈接器將決定可以將其刪除。 因此,構造函數永遠不會被調用,並且 class 永遠不會被注冊。
解決方案是強制 linker 不從庫中刪除任何代碼,即使它認為它沒有使用。 在 iOS 上,可以使用
-force_load
標志完成此步驟,指定庫路徑,在 Linux 上,您需要 --whole--whole-archive
。 這些說服 linker 在剝離方面不要那么激進,並且應該保留全局變量。
但是,我無法將“打開 Linux 你需要 --whole --whole-archive
”變成實際有效的東西。 我是:
我試過添加:
alwayslink=True,
linkopts = ["-Wl,--whole-archive"],
到上面列表中每個 my 目標的 bazel 目標,並沒有什么不同。 我的車輪目標是:
cc_library(
name = "c_api",
# This is the only .so or .so.* in the wheel
srcs=["//:tensorflow/libtensorflow_framework.so.2"],
hdrs = glob([
"tensorflow/include/**/*.h",
"tensorflow/include/**/*.inc",
"tensorflow/include/**/Eigen/**/*",
]),
alwayslink=True,
linkopts = ["-Wl,--whole-archive"],
includes = [
"tensorflow/include",
],
visibility = ["//visibility:public"],
deps = ["@zoox//third_party/cuda:cuda_libs"],
)
以及失敗的實際最終目標:
cc_library(
name = "tensorflow_wrapper",
srcs = ["tensorflow_wrapper.cpp"],
hdrs = ["tensorflow_wrapper.h"],
tags = ["offline-only"],
deps = [
":utils",
"//other/stuff:etc",
# This is the above target for the wheel
"@pypi__tensorflow_python3_deps//:c_api",
],
alwayslink = 1,
linkopts = ["-Wl,--whole-archive"],
)
:c_api
目標足以讓自定義操作正常工作,失敗的 C++ 代碼仍然可以編譯和運行,只是沒有注冊所需的工廠,因此在需要時失敗。
我需要更改什么才能讓 TensorFlow 使用的注冊模式實際執行?
--whole-archive
在這種情況下不起作用。 此標志的全部目的是鏈接static庫(Linux 中的*.a
)中的所有內容。 默認情況下,共享庫包含所有編譯后的代碼,所以你不要那個技巧,因為你使用的是*.so
文件。
也許問題與tensorflow_wrapper
的使用有關。 如果您像這樣從 bazel 鏈接到該庫:
cc_binary(
name="some_binary",
src=["main.cpp"],
deps=["//some/path/to:tensorflow_wrapper"],
)
那么一切都應該正常工作,因為 bazel 知道tensorflow_wrapper
需要什么
但是,如果您想在 bazel 之外使用它,則需要像這樣鏈接libtensorflow_framework.so.2
和libtensorflow_wrapper.so
/ libtensorflow_wrapper.a
:
g++ your_binary_main.cpp -ltensorflow_wrapper -ltensorflow_framework
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.