在TensorFlow的protobufs中存在导入循环。

huangapple go评论91阅读模式
英文:

Import cycle in tensorflow protobufs

问题

我正在尝试编写客户端代码与一个TensorFlow服务器进行通信。我需要tensorflowtensorflow_serving的Golang编译的protobuf文件。这些文件不容易获取,但我通过这个链接成功获取到了。基本上,我使用buf来生成它们。这是buf的yaml配置文件:

version: v1
managed:
  enabled: true
  optimize_for: CODE_SIZE

  # Go
  go_package_prefix:
    default: "some/path"

plugins:
  - plugin: buf.build/protocolbuffers/go
    out: gen/proto/go

这个命令成功运行了,但是应用程序的日志显示:

 package command-line-arguments
     imports my-package/internal/infer
     imports my-package/internal/infer/tensorflow_serving/apis
     imports my-package/internal/infer/tensorflow/core/protobuf
     imports my-package/internal/infer/tensorflow/compiler/xla/stream_executor
     imports my-package/internal/infer/tensorflow/compiler/xla
     imports my-package/internal/infer/tensorflow/compiler/xla/service
     imports my-package/internal/infer/tensorflow/compiler/xla: import cycle not allowed

请注意,tensorflowtensorflow_serving下的所有内容都是直接从原始存储库编译的。

对我来说,像TensorFlow这样广泛使用的库竟然会出现循环导入是令人惊讶的,但也许确实存在这个问题。我该如何解决这个问题呢?

英文:

I am trying to write client code to talk to a tensorflow server. I need the golang compiled protobufs for tensorflow and tensorflow_serving. These are not easy to come by, I managed to do so through this. Basically, using buf to generate them. Here is the buf yaml:

version: v1
managed:
  enabled: true
  optimize_for: CODE_SIZE

  # Go
  go_package_prefix:
    default: "some/path"

plugins:
  - plugin: buf.build/protocolbuffers/go
    out: gen/proto/go

This runs successfully, but running the application logs:

 package command-line-arguments
     imports my-package/internal/infer
     imports my-package/internal/infer/tensorflow_serving/apis
     imports my-package/internal/infer/tensorflow/core/protobuf
     imports my-package/internal/infer/tensorflow/compiler/xla/stream_executor
     imports my-package/internal/infer/tensorflow/compiler/xla
     imports my-package/internal/infer/tensorflow/compiler/xla/service
     imports my-package/internal/infer/tensorflow/compiler/xla: import cycle not allowed

Note that everything under tensorflow and tensorflow_serving is directly compiled from the original repositories.

It is surprising to me that something as widely used as tensorflow should have an import cycle, but maybe it does. How can I resolve this?

答案1

得分: 1

TL;DR

根本原因是https://github.com/tensorflow/tensorflow仓库没有正确组织proto文件(或者至少对Go不友好)。

以下两个文件在Go中导致了循环导入(xla->xla/service->xla):

  • tensorflow/compiler/xla/xla.proto

    • import "tensorflow/compiler/xla/service/hlo.proto"
  • tensorflow/compiler/xla/service/hlo.proto

    • import "tensorflow/compiler/xla/xla_data.proto"

由于xla_data.proto没有导入其他文件,我们可以将其移动到自己的包中以打破循环导入。我们可以利用buf的覆盖功能来实现。这是最终的buf.gen.yaml文件:

version: v1
managed:
  enabled: true
  go_package_prefix:
    default: example.com/mymodule/internal
  override:
    GO_PACKAGE:
      # move the generated xla_data.pb.go file into package xla/data to break the import cycle.
      tensorflow/compiler/xla/xla_data.proto: 'example.com/mymodule/internal/tensorflow/compiler/xla/data'
plugins:
  - name: go
    out: internal
    opt:
      - module=example.com/mymodule/internal

  - name: go-grpc
    out: internal
    opt:
      - module=example.com/mymodule/internal

使用buf编译Tensorflow proto文件的完整设置

以下是最终的目录结构:

├── buf.gen.yaml
├── buf.work.yaml
├── buf.yaml
├── go.mod
├── go.sum
├── internal
│   ├── tensorflow
│   └── tensorflow_serving
└── testdata
    ├── serving
    └── tensorflow

buf.gen.yaml:参见"TL;DR"部分。

buf.work.yaml

version: v1
directories:
  - testdata/serving
  - testdata/tensorflow

buf.yaml

version: v1
breaking:
  use:
    - FILE
lint:
  use:
    - DEFAULT

这是我的环境:

$ go version
go version go1.20.3 linux/amd64
$ buf --version
1.17.0
$ protoc --version
libprotoc 3.12.4
$ protoc-gen-go --version
protoc-gen-go v1.30.0
$ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.3.0
$ git version
git version 2.37.2

现在在此目录的根目录中执行以下命令:

$ go mod init example.com/mymodule
$ go get google.golang.org/grpc
$ git clone https://github.com/tensorflow/tensorflow.git testdata/tensorflow
$ git clone https://github.com/tensorflow/serving.git testdata/serving
$ buf generate
$ go build ./...

注意

  1. TensorFlow仓库被克隆到testdata目录中,以便go build会忽略它们。
  2. 设置将文件生成到internal目录中。您可以修改buf.gen.yaml文件以将它们放置在任何您想要的位置。
  3. go build ./...不会报告任何错误。但我不确定生成的文件是否有效。
英文:

TL;DR

The root cause is that the repositry https://github.com/tensorflow/tensorflow does not organize the proto files correctly (or at least does not make it friendly for Go).

The following two files lead to the import cycle (xla->xla/service->xla) in Go:

  • tensorflow/compiler/xla/xla.proto

    • import "tensorflow/compiler/xla/service/hlo.proto"
  • tensorflow/compiler/xla/service/hlo.proto

    • import "tensorflow/compiler/xla/xla_data.proto"

Since xla_data.proto does not import any other files, we can move it into its own package to break the import cycle. We can utilize the override feature of buf to do this. Here is the final buf.gen.yaml file:

version: v1
managed:
  enabled: true
  go_package_prefix:
    default: example.com/mymodule/internal
  override:
    GO_PACKAGE:
      # move the generated xla_data.pb.go file into package xla/data to break the import cycle.
      tensorflow/compiler/xla/xla_data.proto: 'example.com/mymodule/internal/tensorflow/compiler/xla/data'
plugins:
  - name: go
    out: internal
    opt:
      - module=example.com/mymodule/internal

  - name: go-grpc
    out: internal
    opt:
      - module=example.com/mymodule/internal

The Full Setup to Compile Tensorflow proto Files with buf

Here is the final directory structure:

├── buf.gen.yaml
├── buf.work.yaml
├── buf.yaml
├── go.mod
├── go.sum
├── internal
│   ├── tensorflow
│   └── tensorflow_serving
└── testdata
    ├── serving
    └── tensorflow

buf.gen.yaml: see the "TL;DR" section.

buf.work.yaml:

version: v1
directories:
  - testdata/serving
  - testdata/tensorflow

buf.yaml:

version: v1
breaking:
  use:
    - FILE
lint:
  use:
    - DEFAULT

Here is my environment:

$ go version
go version go1.20.3 linux/amd64
$ buf --version
1.17.0
$ protoc --version
libprotoc 3.12.4
$ protoc-gen-go --version
protoc-gen-go v1.30.0
$ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.3.0
$ git version
git version 2.37.2

Now execute the following commands in the root of this directory:

$ go mod init example.com/mymodule
$ go get google.golang.org/grpc
$ git clone https://github.com/tensorflow/tensorflow.git testdata/tensorflow
$ git clone https://github.com/tensorflow/serving.git testdata/serving
$ buf generate
$ go build ./...

Notes:

  1. The tensorflow repositories are cloned into the testdata directory so that go build will ignore them.
  2. The setup generates the files into the internal directory. You can modify the buf.gen.yaml file to place them anywhere you want.
  3. go build ./... does not report any error. But I'm not sure whether the generated files are valid or not.

huangapple
  • 本文由 发表于 2023年4月19日 09:04:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76050040.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定