【问题标题】:How to load custom op library when using c++?使用 c++ 时如何加载自定义操作库?
【发布时间】:2020-01-11 09:59:25
【问题描述】:

我用 bazel 构建了一个非常简单的自定义操作 zero_out.dll,它在使用 python 时可以工作。

import tensorflow as tf
zero_out_module = tf.load_op_library('./zero_out.dll')
with tf.Session(''):
  zero_out_module.zero_out([[1, 2], [3, 4]]).eval()

但是我必须使用 C++ 来运行推理,是否有任何与tf.load_op_library 具有相似功能的 c++ api,因为在 tf.load_op_library 中似乎已经完成了很多注册工作,TF 没有对应的 c++ API?

【问题讨论】:

  • Dynamically load a function from a DLL 的可能重复项。 DLL 和此类功能是通过 Windows API 处理的。
  • @Romen 这并不是真正的重复,因为 TensorFlow 库加载做了一些特殊的额外工作来注册加载的操作/内核。
  • @jdehsa,我认为无论如何这可能是一个有用的链接。我也找不到从 C++ TensorFlow API 的库中加载操作的等效方法。

标签: c++ tensorflow


【解决方案1】:

虽然 C++ 中似乎没有公共 API,但库加载函数在 TensorFlow API for C 中公开(这是 tf.load_library 使用的 API)。它没有“好”的文档,但您可以在 c/c_api.h 中找到它们:

// --------------------------------------------------------------------------
// Load plugins containing custom ops and kernels

// TF_Library holds information about dynamically loaded TensorFlow plugins.
typedef struct TF_Library TF_Library;

// Load the library specified by library_filename and register the ops and
// kernels present in that library.
//
// Pass "library_filename" to a platform-specific mechanism for dynamically
// loading a library. The rules for determining the exact location of the
// library are platform-specific and are not documented here.
//
// On success, place OK in status and return the newly created library handle.
// The caller owns the library handle.
//
// On failure, place an error status in status and return NULL.
TF_CAPI_EXPORT extern TF_Library* TF_LoadLibrary(const char* library_filename,
                                                 TF_Status* status);

// Get the OpList of OpDefs defined in the library pointed by lib_handle.
//
// Returns a TF_Buffer. The memory pointed to by the result is owned by
// lib_handle. The data in the buffer will be the serialized OpList proto for
// ops defined in the library.
TF_CAPI_EXPORT extern TF_Buffer TF_GetOpList(TF_Library* lib_handle);

// Frees the memory associated with the library handle.
// Does NOT unload the library.
TF_CAPI_EXPORT extern void TF_DeleteLibraryHandle(TF_Library* lib_handle);

这些函数确实调用了 C++ 代码(参见c/c_api.cc 中的源代码)。但是,在core/framework/load_library.cc 中定义的调用函数没有要包含的标头。在c/c_api.cc 中使用的 C++ 代码中使用它的解决方法是自己声明函数,并链接 TensorFlow 库。

namespace tensorflow {
// Helpers for loading a TensorFlow plugin (a .so file).
Status LoadLibrary(const char* library_filename, void** result,
                   const void** buf, size_t* len);
}

据我所知,没有用于卸载库的 API。 C API 只允许您删除库句柄对象。这只是通过释放指针来完成,但如果你想避免麻烦,你可能应该使用 TensorFlow 提供的释放函数 tensorflow::port:free,在 core/platform/mem.h 中声明。同样,如果您不能或不想包含它,您可以自己声明该函数,它应该也可以工作。

namespace tensorflow {
namespace port {
void Free(void* ptr);
}
}

【讨论】:

  • 非常有用的信息!我尝试使用TF_LoadLibrary #include "c_api.h" TF_Status* status_load = TF_NewStatus(); TF_Library* lib_handle = TF_LoadLibrary("C:\\custom_op\\zero_out.dll", status_load); cout << "message: " << TF_Message(status_load) << endl; 加载lib,但它显示zero_out.dll not found。顺便说一句,我在 Windows 中使用 bazel 构建了 TF lib 和自定义 op dll。好像有些依赖没有找到,我在zero_out.dll之外放了tensorflow.dll
  • @7oud 奇怪,但我自己没有尝试过这些,所以我不知道会出现什么问题。如果您查看LoadLibrary for Windows 的impl,在core/platform/windows/env.cc 中,您似乎确实应该使用绝对路径(因为使用了LOAD_WITH_ALTERED_SEARCH_PATH)......但看起来您得到的错误实际上只是意味着LoadLibraryExW 失败,所以可能是别的原因。
  • @jdejesa 我发现python36.dll 是必需的,即使它没有被使用。现在TF_Code code = TF_GetCode(status_load);返回码是TF_OK,然后我用TF_Buffer op_list_buf = TF_GetOpList(lib_handle);获取操作列表,但是op_list_buf.length返回0,能否给一些代码sn-p来获取自定义操作库中的接口函数?跨度>
  • @7oud 奇怪,你需要 Python dll,C lib 的重点是自包含。不管怎样,关于TF_GetOpList,我自己没用过这些,所以我不确定。你应该从TF_Buffer 中的data 中创建一个OpList 消息(例如使用ParseFromArray) - 如果长度为零,我猜它是一个空列表。注册操作可能有问题?
  • @Fisa 不,如果您使用 Python 中的tf.load_op_library,则无需执行任何其他操作,这是 Python 的正常 TensorFlow 分发的一部分。 C API 仅适用于您想使用不同的编程语言运行模型的情况,例如C 或 C++,并且需要使用来自外部库的操作(因此您需要一种方法来在该语言中执行与 tf.load_op_library 等效的操作)。
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多