安装 go 版 TensorFlow的问题记录

文章记录在centos 7上安装golang环境及go版TensorFlow的过程及中间遇到的问题及解决方法。

1 安装golang环境

环境是宿主机安装virtualbox加载的centos 7环境,采用的yum源安装。此部分参考此文 CentOS7安装golang

yum -y install golang

安装完成后,查看

[root@localhost ~]# go version
go version go1.13.14 linux/amd64
[root@localhost ~]# 

设置环境变量,在home目录创建GOPATH目录

[root@localhost home]# mkdir gopath^C
[root@localhost home]# 
[root@localhost home]# 
[root@localhost home]# ll
总用量 16548
drwxr-xr-x.  4 root root       99 8月  27 15:45 gopath
-rwxr-xr-x.  1 root root     8496 8月  26 18:00 hello_tf
-rw-r--r--.  1 root root      151 8月  26 18:00 hello_tf.c
drwxr-xr-x.  3 root root       22 8月  27 07:52 openblas
drwxr-xr-x. 19  501  501     4096 8月  27 11:31 Python-3.7.0
-rw-r--r--.  1 root root 16922100 8月  27 10:29 Python-3.7.0.tar.xz
[root@localhost home]# 

编辑/root/.bashrc文件,添加如下信息

export GOPATH=/home/gopath
export GOROOT=/usr/lib/golang
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN

重新加载/root/.bashrc文件

source /root/.bashrc

查看go的相关设置是否生效

[root@localhost home]# go env
GO111MODULE=""
GOARCH="amd64"
GOBIN="/usr/lib/golang/bin"
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/gopath"
GOPRIVATE=""
GOPROXY="direct"
GOROOT="/usr/lib/golang"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build389723181=/tmp/go-build -gno-record-gcc-switches"
[root@localhost home]# 

环境设置已完成,进行测试,在/home/gopath下编写测试程序

[root@localhost gopath]# vim test.go 
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}

保存后,输入命令

go build test.go

在输入

[root@localhost gopath]# ./test 
Hello world!
[root@localhost gopath]#

测试go已经配置完成。过程很顺利的完成。

2 安装C版TensorFlow

此部分是按照 安装 Go 版 TensorFlow 中的说明,先设置TensorFlow C 库,安装过程参考 安装 C 版 TensorFlow

2.1安装压缩包

下载:https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.15.0.tar.gz

webget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.15.0.tar.gz

解压缩下载的归档文件,其中包含要添加到 C 程序中的头文件以及要与之关联的共享库。在 Linux 和 macOS 上,您可能需要解压缩到 /usr/local/lib:

sudo tar -C /usr/local -xzf (downloaded file)

在 Linux/macOS 上,如果将 TensorFlow C 库解压缩到系统目录(例如 /usr/local),请使用 ldconfig 配置链接器:

sudo ldconfig

2.2编译

安装 TensorFlow C 库后,使用以下源代码创建一个示例程序 (hello_tf.c):

#include <stdio.h>
#include <tensorflow/c/c_api.h>

int main() {
  printf("Hello from TensorFlow C library version %s\n", TF_Version());
  return 0;
}

编译示例程序以创建可执行文件,然后运行以下命令:

gcc hello_tf.c -ltensorflow -o hello_tf

./hello_tf

执行上述命令后报错如下:

[root@localhost local]# ./hello_tf
./hello_tf: error while loading shared libraries: libtensorflow.so.1: cannot open shared object file: No such file or directory

百度相关后,找到如下解决方案:

$ gcc -I/usr/local/include -L/usr/local/lib hello_tf.c -ltensorflow -o hello_tf
 $ ./hello_tf 
 ./hello_tf: error while loading shared libraries: libtensorflow.so.1: cannot open shared object file: No such file or directory
 $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
 $ ./hello_tf 
 Hello from TensorFlow C library version 1.14.0
 $ unset LD_LIBRARY_PATH 
 $ ./hello_tf 
 ./hello_tf: error while loading shared libraries: libtensorflow.so.1: cannot open shared object file: No such file or directory

基于该方案,设置LD_LIBRARY_PATH,如下所示:

[root@localhost local]# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
[root@localhost local]# ./hello_tf
Hello from TensorFlow C library version 1.15.0
[root@localhost local]# 

另一种解决方案(备注该方案为佳),打开/etc/ld.so.conf文件,增加/usr/local/lib,主要操作如下:

[root@localhost lib]# cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/lib

而后执行ldconfig

[root@localhost lib]# ldconfig
[root@localhost lib]# 

此方法参考 Suppressed: java.lang.UnsatisfiedLinkError: libxxx.so: 无法打开共享对象文件: 没有那个文件或目录

3 安装 Go 版 TensorFlow

此部分是按照 安装 Go 版 TensorFlow 的说明逐步进行的,中间有很多问题,后基于网上一些建议调整安装成功。

3.1安装过程

在设置完C 版 TensorFlow相关配置后,进行go版TensorFlow的安装,使用命令

go get github.com/tensorflow/tensorflow/tensorflow/go

我在安装的过程中,经常出现如下的问题

[root@localhost gopath]# go get -d -v github.com/tensorflow/tensorflow/tensorflow/go
github.com/tensorflow/tensorflow (download)
# cd .; git clone -- https://github.com/tensorflow/tensorflow /home/gopath/src/github.com/tensorflow/tensorflow
error: RPC failed; result=18, HTTP code = 200
fatal: The remote end hung up unexpectedly
fatal: 过早的文件结束符(EOF)
fatal: index-pack failed
package github.com/tensorflow/tensorflow/tensorflow/go: exit status 128
[root@localhost gopath]#

分析发现是先从GitHub上clone相关的文件到本机,所以在/home/gopath目录尝试了如下命令

git clone -- https://github.com/tensorflow/tensorflow /home/gopath/src/github.com/tensorflow/tensorflow

就是使用git clone到本机,但该命令经常在达到10%左右就卡住,不在下载了。故采取从浏览器下载到宿主机在上传到虚拟机的方式进行,打开GitHub的TensorFlow地址,前期在是哟用rasa时用的是TensorFlow的1.13.1版本,故这里也下载1.13.1的版本,下载得到tensorflow-1.13.1.zip压缩包,修改名称为tensorflow.zip,而后通过rz命令上传到宿主机

[root@localhost gopath]# cd src/github.com/
[root@localhost github.com]# ll
总用量 40544
drwxr-xr-x. 3 root root       22 8月  27 15:30 golang
drwxr-xr-x. 3 root root       18 8月  26 18:22 gonum
drwxr-xr-x. 3 root root       26 8月  27 07:56 mattn
drwxr-xr-x. 3 root root       25 8月  27 07:56 olekukonko
drwxr-xr-x. 3 root root       19 8月  27 07:56 peterh
drwxr-xr-x. 3 root root       20 8月  27 07:55 pkg
drwxr-xr-x. 4 root root       32 8月  27 07:55 spf13
drwxr-xr-x. 3 root root       24 8月  27 15:31 tensorflow
-rw-r--r--. 1 root root 41515134 8月  27 15:22 tensorflow.zip
drwxr-xr-x. 3 root root       18 8月  27 07:53 ynqa
[root@localhost github.com]#

解压tensorflow.zip,得到tensorflow目录,回到/home/gopath目录进行构建,命令如下

[root@localhost gopath]# go generate github.com/tensorflow/tensorflow/tensorflow/go/op
can't load package: package github.com/tensorflow/tensorflow/tensorflow/go/op: cannot find package "github.com/tensorflow/tensorflow/tensorflow/go/op" in any of:
        /usr/lib/golang/src/github.com/tensorflow/tensorflow/tensorflow/go/op (from $GOROOT)
        /home/gopath/src/github.com/tensorflow/tensorflow/tensorflow/go/op (from $GOPATH)
[root@localhost gopath]#

报错,说找不到该目录,下载的源码怎么没有该目录内,直接cd查看

[root@localhost gopath]# cd /home/gopath/src/github.com/tensorflow/tensorflow/tensorflow/go/op
-bash: cd: /home/gopath/src/github.com/tensorflow/tensorflow/tensorflow/go/op: 没有那个文件或目录
[root@localhost gopath]# cd /home/gopath/src/github.com/tensorflow/tensorflow/tensorflow/go/
-bash: cd: /home/gopath/src/github.com/tensorflow/tensorflow/tensorflow/go/: 没有那个文件或目录
[root@localhost gopath]#

确实没有该目录,回到解压处查看,发现源码解压后只有两层tensorflow,而go get的有三层,则我们直接增加一层tensorflow,在进行构建

[root@localhost gopath]# go generate github.com/tensorflow/tensorflow/tensorflow/go/op

package google.golang.org/protobuf/encoding/prototext: unrecognized import path "google.golang.org/protobuf/encoding/prototext" (https fetch: Get https://google.golang.org/protobuf/encoding/prototext?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/encoding/protowire: unrecognized import path "google.golang.org/protobuf/encoding/protowire" (https fetch: Get https://google.golang.org/protobuf/encoding/protowire?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/proto: unrecognized import path "google.golang.org/protobuf/proto" (https fetch: Get https://google.golang.org/protobuf/proto?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/reflect/protoreflect: unrecognized import path "google.golang.org/protobuf/reflect/protoreflect" (https fetch: Get https://google.golang.org/protobuf/reflect/protoreflect?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/reflect/protoregistry: unrecognized import path "google.golang.org/protobuf/reflect/protoregistry" (https fetch: Get https://google.golang.org/protobuf/reflect/protoregistry?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/runtime/protoiface: unrecognized import path "google.golang.org/protobuf/runtime/protoiface" (https fetch: Get https://google.golang.org/protobuf/runtime/protoiface?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
package google.golang.org/protobuf/runtime/protoimpl: unrecognized import path "google.golang.org/protobuf/runtime/protoimpl" (https fetch: Get https://google.golang.org/protobuf/runtime/protoimpl?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
../genop/main.go:17: running "bash": exit status 1
src/github.com/tensorflow/tensorflow/tensorflow/go/op/generate.go:17: running "go": exit status 1
[root@localhost gopath]# 

报错protobuf导入超时

import path "google.golang.org/protobuf/runtime/protoimpl" (https fetch: Get https://google.golang.org/protobuf/runtime/protoimpl?go-get=1: dial tcp 216.239.37.1:443: i/o timeout

解决方法参考 go get 找不到 google.golang.org/protobuf github.com/gin-gonic/gin 解决办法 也就是从GitHub上clone代码下来,如下操作

[root@localhost gopath]# mkdir -p $GOPATH/src/google.golang.org
[root@localhost gopath]# git clone https://e.coding.net/robinqiwei/googleprotobuf.git $GOPATH/src/google.golang.org/protobuf
正克隆到 '/home/gopath/src/google.golang.org/protobuf'...
remote: Enumerating objects: 13821, done.
remote: Counting objects: 100% (13821/13821), done.
remote: Compressing objects: 100% (5172/5172), done.
remote: Total 13821 (delta 8112), reused 13821 (delta 8112), pack-reused 0
接收对象中: 100% (13821/13821), 7.44 MiB | 932.00 KiB/s, done.
处理 delta 中: 100% (8112/8112), done.
[root@localhost gopath]# 

完成后,在重新构建成功,如下

[root@localhost gopath]# go generate github.com/tensorflow/tensorflow/tensorflow/go/op
# github.com/golang/protobuf/protoc-gen-go
../../../../../golang/protobuf/protoc-gen-go/main.go:71:6: gen.SupportedFeatures undefined (type *protogen.Plugin has no field or method SupportedFeatures)
../../../../../golang/protobuf/protoc-gen-go/main.go:71:27: undefined: internal_gengo.SupportedFeatures
../genop/main.go:17: running "bash": exit status 2
src/github.com/tensorflow/tensorflow/tensorflow/go/op/generate.go:17: running "go": exit status 1
[root@localhost gopath]#

这里发现exit status 1,也不知是啥问题,没有去研究了。然后验证安装结果

[root@localhost gopath]# go test github.com/tensorflow/tensorflow/tensorflow/go
ok      github.com/tensorflow/tensorflow/tensorflow/go  1.848s
[root@localhost gopath]# 

程序验证,GO示例,创建tf-hello.go

[root@localhost gopath]# vim tf-hello.go 

package main

import (
    tf "github.com/tensorflow/tensorflow/tensorflow/go"
    "github.com/tensorflow/tensorflow/tensorflow/go/op"
    "fmt"
)
func main() {
    // Construct a graph with an operation that produces a string constant.
    s := op.NewScope()
    c := op.Const(s, "Hello from TensorFlow version " + tf.Version())
    graph, err := s.Finalize()
    if err != nil {
        panic(err)
    }
    // Execute the graph in a session.
    sess, err := tf.NewSession(graph, nil)
    if err != nil {
        panic(err)
    }
    output, err := sess.Run(nil, []tf.Output{c}, nil)
    if err != nil {
        panic(err)
    }
    fmt.Println(output[0].Value())
}

执行

[root@localhost gopath]# go run tf-hello.go
2020-08-27 15:44:47.868756: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
2020-08-27 15:44:47.882914: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 1799995000 Hz
2020-08-27 15:44:47.884161: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x22d3190 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2020-08-27 15:44:47.884211: I tensorflow/compiler/xla/service/service.cc:176]   StreamExecutor device (0): Host, Default Version
Hello from TensorFlow version 1.15.0
[root@localhost gopath]#

C示例,C和Go实际上共用了相同的动态链接库和头文件,安装好Go版本后,C的API可以直接使用。创建tf.c

[root@localhost gopath]# vim tf.c 

#include <stdio.h>
#include <tensorflow/c/c_api.h>

int main() {
    printf("Hello from TensorFlow C library version %s\n", TF_Version());
    return 0;
}

编译,执行

[root@localhost gopath]# gcc -I/usr/local/include -L/usr/local/lib tf.c -ltensorflow
[root@localhost gopath]# ll
总用量 1988
-rwxr-xr-x. 1 root root    8496 8月  27 15:45 a.out
drwxr-xr-x. 3 root root      25 8月  27 15:40 pkg
drwxr-xr-x. 5 root root      65 8月  27 15:40 src
-rwxr-xr-x. 1 root root 2008751 8月  26 17:56 test
-rw-r--r--. 1 root root      74 8月  26 17:56 test.go
-rw-r--r--. 1 root root     157 8月  27 15:45 tf.c
-rw-r--r--. 1 root root     671 8月  27 15:44 tf-hello.go
[root@localhost gopath]# ./a.out 
Hello from TensorFlow C library version 1.15.0
[root@localhost gopath]# 

至此,整个环境已经整合完成,后续准备使用golang调用TensorFlow模型。