未定义的符号'fixed_address_empty_string':带有protobuf的新张量流运算
Undefined symbol 'fixed_address_empty_string' : new tensorflow op with protobuf
我想创建一个可以与 外部 Python 进程。在妈妈那里,我创建了一个新操作 这将发送到带有protobuf
的 Python 进程"hello world"。
在这个小示例中,我发送了一个字符串。将来我想 发送更复杂的数据,如特征矩阵,这就是我选择protobuf
.(以及可能的"轻松集成到张量流中)。
msg.proto:
package prototest;
message Foo {
required string bar = 1;
}
protoc msg.proto --cpp_out=. --python_out=.
- 生成 :
msg.pb.cc msg.pb.h msg_pb2.py
hello_world.cc:
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor_shape.h"
#include "tensorflow/core/platform/default/logging.h"
#include "tensorflow/core/framework/shape_inference.h"
// to send serialized data through UPD socket
#include <sys/socket.h>
#include <arpa/inet.h>
// generated header file from protoc
#include "msg.pb.h"
namespace tensorflow{
namespace shape_inference{
Status HelloWorldShape(InferenceContext* c){
std::cout << "shape_infernce is done" << std::endl;
return Status::OK();
}
REGISTER_OP("HelloWorld")
.SetShapeFn(HelloWorldShape)
.Doc(R"doc(HelloWorld operation)doc");
} // end namespace shape_inference
class HelloWorldOp : public OpKernel {
public :
// constructor
explicit HelloWorldOp(OpKernelConstruction* context) : OpKernel(context) {
std::cout << "HelloWorldOp constructor" << std::endl;
}
void Compute(OpKernelContext* context) override {
std::cout << "Start Compute method" << std::endl;
//-----------------------------------------------------------------
// send something to a Python process with protobuf
struct sockaddr_in addr;
addr.sin_family = AF_INET;
inet_aton("127.0.0.1", &addr.sin_addr);
addr.sin_port = htons(5555);
// initialise a foo and set some properties
GOOGLE_PROTOBUF_VERIFY_VERSION;
prototest::Foo foo;
foo.set_bar("Hello World");
// serialise to string, this one is obvious ; )
std::string buf;
foo.SerializeToString(&buf);
int sock = socket(PF_INET, SOCK_DGRAM, 0);
sendto(sock, buf.data(), buf.size(), 0, (struct sockaddr *)&addr, sizeof(addr));
//------------------------------------------------------------------
std::cout << "Compute method is done" << std::endl;
}
};
REGISTER_KERNEL_BUILDER(Name("HelloWorld").Device(DEVICE_CPU), HelloWorldOp);
} // end namespace tensorflow
为了编译和运行我的代码,我使用在 #10950 中找到的测试脚本
compiler_and_run.py:
#!/usr/bin/env python3.5
# Demo from https://github.com/tensorflow/tensorflow/issues/10950
from __future__ import print_function
import os
import sys
import tensorflow as tf
my_dir = os.path.dirname(os.path.abspath(__file__))
so_filename = "lib_hello_world.so"
cc_filename = "hello_world.cc"
def compile():
# Fix for undefined symbol: _ZN6google8protobuf8internal26fixed_address_empty_stringE.
# https://github.com/tensorflow/tensorflow/issues/1419
from google.protobuf.pyext import _message as msg
lib = msg.__file__
ld_flags = [
"-Xlinker", "-rpath", "-Xlinker", os.path.dirname(lib),
"-L", os.path.dirname(lib), "-l", ":" + os.path.basename(lib)]
common_opts = ["-shared", "-O2", "-std=c++11"]
if sys.platform == "darwin":
common_opts += ["-undefined", "dynamic_lookup"]
common_opts += ["-I", tf.sysconfig.get_include()]
common_opts += ["-fPIC"]
common_opts += ["-D_GLIBCXX_USE_CXX11_ABI=0"] # might be obsolete in the future
opts = common_opts + [cc_filename, "-o", so_filename]
opts += ld_flags
cmd_bin = "g++"
cmd_args = [cmd_bin] + opts
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
print("compile call: %s" % " ".join(cmd_args))
proc = Popen(cmd_args, stdout=PIPE, stderr=STDOUT)
stdout, stderr = proc.communicate()
assert stderr is None # should only have stdout
if proc.returncode != 0:
print("compile failed: %s" % cmd_bin)
print("Original stdout/stderr:")
print(stdout)
raise CalledProcessError(returncode=proc.returncode, cmd=cmd_args)
assert os.path.exists(so_filename)
def main():
print("TensorFlow version:", tf.GIT_VERSION, tf.VERSION)
os.chdir(my_dir)
compile()
mod = tf.load_op_library("%s/%s" % (my_dir, so_filename))
if __name__ == "__main__":
main()
这将返回:
TensorFlow version: v1.2.0-rc2-21-g12f033d 1.2.0
compile call: g++ -shared -O2 -std=c++11 -I /usr/local/lib/python3.5/dist-packages/tensorflow/include -fPIC -D_GLIBCXX_USE_CXX11_ABI=0 hello_world.cc -o lib_hello_world.so -Xlinker -rpath -Xlinker /usr/local/lib/python3.5/dist-packages/protobuf-3.2.0-py3.5-linux-x86_64.egg/google/protobuf/pyext -L /usr/local/lib/python3.5/dist-packages/protobuf-3.2.0-py3.5-linux-x86_64.egg/google/protobuf/pyext -l :_message.cpython-35m-x86_64-linux-gnu.so
Traceback (most recent call last):
File "./compile_and_test.py", line 55, in <module>
main()
File "./compile_and_test.py", line 51, in main
mod = tf.load_op_library("%s/%s" % (my_dir, so_filename))
File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/framework/load_library.py", line 64, in load_op_library
None, None, error_msg, error_code)
tensorflow.python.framework.errors_impl.NotFoundError: /src/ext_hello_world/lib_hello_world.so: undefined symbol: _ZN6google8protobuf8internal26fixed_address_empty_stringE
编译似乎有效(没有致命错误)。但是tf.load_op_library()
由于共享库 (*.so) 中未定义的库而失败。
这个未定义的符号似乎来自protobuf。
我自己安装了protoc
(请参阅有关它的说明)。
在tf.sysconfig.get_include()
中,有一个google/protobuf
文件夹,其中包含来自构建的张量流的头文件。
所以我不知道编译过程中使用了哪些头文件: - 来自包含张量流文件的头文件 ? - 手动安装的protobuf的头文件?
还是这个未定义的符号不是由于这个事实?
- 如何解决共享库中的此未定义符号错误?
- 我可以从
tensorflow/includes/google/protobuf
开始安装protoc
吗?(而不是从头开始)
我观察到在#10950中:
from google.protobuf.pyext import _message as msg
lib = msg.__file__
返回 :/u/zeyer/.local/lib/python2.7/site-packages/google/protobuf/pyext/_message.so
就我而言,它是:/usr/local/lib/python3.5/dist-packages/protobuf-3.2.0-py3.5-linux-x86_64.egg/google/protobuf/pyext/_message.cpython-35m-x86_64-linux-gnu.so
这个关于 protobuf 的文件似乎完全不同......
关于原型安装的注意事项: 未安装protoc
(protobuf 编译器)。 我确定了 protobuf 在张量流中使用的版本:v3.2.0 !
之后,我遵循了protobuf安装说明(C++和Python实现)。
cd /opt/
# clone protobuf repo
git clone https://github.com/google/protobuf.git
cd protobuf
# change to the right branch
# list tags
git tag -l
git checkout tags/v3.2.0
# install protobuf
apt-get install autoconf automake libtool curl make g++ unzip
./autogen.sh
./configure
make
make check
make install
ldconfig
# protoc version
protoc --version
>>> libprotoc 3.2.0
# print linker and compiler files
pkg-config --cflags --libs protobuf
>>> -pthread -I/usr/local/include -L/usr/local/lib -lprotobuf -pthread -lpthread
#some useful env variables
PB_INC=$(pkg-config --cflags protobuf)
PB_LINK=$(pkg-config --libs protobuf)
TF_INC=$(python3.5 -c 'import tensorflow as tf; print(tf.sysconfig.get_include())')
TF_LIBS=$(find $TF_INC/../ -name "*.so")
# here, I used python3.5
cd python
export LD_LIBRARY_PATH=../src/.libs
python3.5 setup.py build --cpp_implementation
python3.5 setup.py test --cpp_implementation
python3.5 setup.py install --cpp_implementation
系统信息
码头工人- :码头工人版本 1.12.6,内部版本 78d1802
- 图片 : Tensorflow/TensorFlow:1.2.0-devel-GPU-PY3
- 基于 : Ubuntu 16.04 (4.4.0-78-通用)
- 从源代码构建张量流
- 张量流版本 : 1.2.0
- python版本:Python 3.5.2
- 巴泽尔版本:
Build label: 0.4.5 Build target: bazel-out/local-fastbuild/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar Build time: Thu Mar 16 12:19:38 2017 (1489666778) Build timestamp: 1489666778 Build timestamp as int: 1489666778
- 海湾合作委员会 -V : ``` 使用内置规范。 COLLECT_GCC=海湾合作委员会 COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper 目标:x86_64-linux-gnu 配置: ../src/configure -v --with-pkgversion='Ubuntu 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-include-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/--enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 螺纹型号:磅 gcc 版本 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
来自 https://github.com/tensorflow/tensorflow/tree/master/tools/tf_env_collect.sh 的信息 :
== cat /etc/issue ===============================================
Linux 2b98f5ebc987 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
VERSION="16.04.2 LTS (Xenial Xerus)"
VERSION_ID="16.04"
VERSION_CODENAME=xenial
== are we in docker =============================================
Yes
== compiler =====================================================
c++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
== uname -a =====================================================
Linux 2b98f5ebc987 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
== check pips ===================================================
numpy (1.13.0)
protobuf (3.3.0)
tensorflow (1.2.0)
== check for virtualenv =========================================
False
== tensorflow import ============================================
tf.VERSION = 1.2.0
tf.GIT_VERSION = v1.2.0-rc2-21-g12f033d
tf.COMPILER_VERSION = v1.2.0-rc2-21-g12f033d
Sanity check: array([1], dtype=int32)
== env ==========================================================
LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:/usr/local/nvidia/lib:/usr/local/nvidia/lib64
DYLD_LIBRARY_PATH is unset
== nvidia-smi ===================================================
Wed Aug 23 17:24:13 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 370.28 Driver Version: 370.28 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce 940MX Off | 0000:01:00.0 Off | N/A |
| N/A 54C P0 N/A / N/A | 277MiB / 2002MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
== cuda libs ===================================================
/usr/local/cuda-8.0/targets/x86_64-linux/lib/libcudart_static.a
/usr/local/cuda-8.0/targets/x86_64-linux/lib/libcudart.so.8.0.61
它来自对 dll 库 libprotobuf[d].lib 的链接,没有指定 -DPROTOBUF_USE_DLLS。
有关详细信息,请参阅自述文件中的"DLL 与静态链接"。
我不认为TensorFlow导出足够的符号来依赖它来实现协议缓冲区。相反,您可以动态链接到已安装的系统协议缓冲区实现。这可能需要匹配 TensorFlow 协议缓冲区版本以避免符号冲突。
我正在使用libprotoc 3.3.0使用TensorFlow 1.3.0(Python 3.4)进行测试。我已将msg.pb.cc
(protoc msg.proto --cpp_out=. --python_out=.
的输出)添加到编译命令(该命令链接到消息的C++实现中),以及pkg-config --cflags --libs protobuf
的输出,以便链接到系统协议缓冲区库。此过程对我有用:
protoc msg.proto --cpp_out=. --python_out=.
g++ -shared -O2 -std=c++11 -I /usr/local/lib/python3.4/dist-packages/tensorflow/include -fPIC -D_GLIBCXX_USE_CXX11_ABI=0 hello_world.cc msg.pb.cc -o lib_hello_world.so $(pkg-config --cflags --libs protobuf)
python3 -c "import tensorflow as tf; tf.Session().run(tf.load_op_library('./lib_hello_world.so').hello_world())"
由于您已经序列化了协议缓冲区,因此在 Python 中反序列化它应该没有问题;次要的 protobuf 版本不需要匹配,因为它是有线格式。
- Cpp-Tuple使用带有变量的get
- 当在带有Eigen的C++中使用GDB时,我如何才能看到更多的大矩阵
- C++中带有List类的迭代器Segfault
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- 在C应用程序中运行C++(带有STL)函数
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- C++使用数组作为多维数组,尽管将其初始化为带有指针的 1D
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 发送一个带有libcurl C++问题的帖子请求:s
- 当使用带有VS2019或VSCode的虚幻引擎4.24.2时,我如何修复这些错误的Intellisense错误
- 带有指定长度字符* 参数的 std::regex_search 在 VS2017 中不起作用?
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何处理linux终端中带有负号(-)的C++中的命令行参数
- 带有Protobuf序列化的C++Hazelcast:字符串不是UTF-8格式的
- 未定义的符号'fixed_address_empty_string':带有protobuf的新张量流运算
- 带有C++插件的Protobuf
- 在Windows、Visual Studio 2013上使用带有cmake库的谷歌protobuf
- 带有协议缓冲区的程序无法使用 MinGW-w64 编译:"undefined reference to google::protobuf:: ..."
- 在c++中解析带有protobuf分段错误的Zeromq