Skip to content

Commit 8355607

Browse files
committed
update readmes and add client examples
remove project local platform targets in favor of using bazel-tools
1 parent f4feb7d commit 8355607

File tree

13 files changed

+660
-58
lines changed

13 files changed

+660
-58
lines changed

.bazelrc

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@ build --define=use_fast_cpp_protos=true
1717
build --define=allow_oversize_protos=true
1818
build --define=grpc_no_ares=true
1919

20-
# build with shared gnu libstdc++ instead of static libc++
21-
build:gnulibcpp --@com_github_emacski_bazeltools//toolchain/cpp/clang:use_libcpp="libstdc++"
22-
build:gnulibcpp --cxxopt=-D_GLIBCXX_USE_CXX11_ABI=0
20+
# platform config groups
2321

24-
build:linux_amd64 --platforms=//:linux_amd64
22+
build:linux_amd64 --platforms=@com_github_emacski_bazeltools//platform:linux_amd64
23+
# boringssl requires legacy toolchain resolution
24+
build:linux_amd64 --crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
25+
build:linux_amd64 --cpu=k8
2526

26-
build:linux_arm64 --platforms=//:linux_arm64
27-
# for boringssl
27+
build:linux_arm64 --platforms=@com_github_emacski_bazeltools//platform:linux_arm64
28+
# boringssl requires legacy toolchain resolution
2829
build:linux_arm64 --crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
2930
build:linux_arm64 --cpu=aarch64
3031

31-
build:linux_arm --platforms=//:linux_arm
32-
# for boringssl
32+
build:linux_arm --platforms=@com_github_emacski_bazeltools//platform:linux_arm
33+
# boringssl requires legacy toolchain resolution
3334
build:linux_arm --crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
3435
build:linux_arm --cpu=arm
3536

BUILD

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1 @@
1-
# Copyright 2020 Erik Maciejewski
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
15-
package(default_visibility = ["//visibility:public"])
16-
17-
platform(
18-
name = "linux_amd64",
19-
constraint_values = [
20-
"@platforms//os:linux",
21-
"@platforms//cpu:x86_64",
22-
],
23-
)
24-
25-
platform(
26-
name = "linux_arm64",
27-
constraint_values = [
28-
"@platforms//os:linux",
29-
"@platforms//cpu:aarch64",
30-
],
31-
)
32-
33-
platform(
34-
name = "linux_arm",
35-
constraint_values = [
36-
"@platforms//os:linux",
37-
"@platforms//cpu:arm",
38-
],
39-
)
1+
# intentionally blank

README.md

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,55 @@ standalone grpc api clients targeting popular arm architectures from an x86_64 h
99
Currently, client libraries can be cross-built for c++, python and go targeting
1010
`linux_amd64`, `linux_arm64` and `linux_arm`.
1111

12+
## Contents
13+
* [Cross-Building](#cross-building)
14+
* [Project Artifacts](#project-artifacts)
15+
* [Client Examples](#client-examples)
16+
17+
## Cross-Building
18+
19+
Using the project's development docker image, all platform specific targets in this
20+
project can be cross-built, from an x86_64 host, for the following platforms by
21+
specifying the corresponding config group when building.
22+
23+
| Config Group | CLI Option |
24+
|--------------|----------|
25+
| `linux_amd64` | `--config=linux_amd64` |
26+
| `linux_arm64` | `--config=linux_arm64` |
27+
| `linux_arm` | `--config=linux_arm` |
28+
29+
Docker Devel Image
30+
```sh
31+
git clone git@github.com:emacski/tensorflow-serving-arm-client.git
32+
cd tensorflow-serving-arm-client
33+
# devel image includes all necessary deps to build and run project targets
34+
docker run --rm -ti \
35+
-w /tensorflow-serving-arm-client \
36+
-v $PWD:/tensorflow-serving-arm-client \
37+
emacski/tensorflow-serving-arm-client:latest-devel /bin/bash
38+
```
39+
40+
Examples
41+
```sh
42+
# build platform wheel for 32-bit arm
43+
bazel run //py/wheel:build_platform --config=linux_arm
44+
# build go client library for amd64
45+
bazel build //py:tensorflow_serving --config=linux_amd64
46+
# build go client library for arm64
47+
bazel build //go:tensorflow_serving --config=linux_arm64
48+
```
49+
50+
[Back to Top](#contents)
51+
1252
## Project Artifacts
1353
### Python3 Client Library (Wheels)
1454

15-
Currently, platform specific wheels are published for CPython 3.7 on
16-
`linux_amd64`, `linux_arm64` and `linux_arm`. These wheels are full self-contained
17-
grpc client libs and include the `tensorflow_serving`, (protobuf only) `tensorflow`,
18-
`grpcio` and `protobuf` py packages with corresponding extensions where applicable
19-
(no compiling or dev-tools required on the install host).
55+
Platform specific wheels are published for the current version of python 3
56+
on debian 10 (CPython 3.7) targeting `linux_amd64`, `linux_arm64` and `linux_arm`.
57+
These wheels are full self-contained grpc client libs and include the
58+
`tensorflow_serving`, (protobuf only) `tensorflow`, `grpcio` and `protobuf` py
59+
packages with corresponding extensions where applicable (no compiling or dev-tools
60+
required on the install host).
2061

2162
Additionally, a pure python3 wheel is published that includes the `tensorflow_serving`,
2263
(protobuf only) `tensorflow` packages and depends on external `grpcio` and
@@ -30,7 +71,7 @@ pip install https://github.com/emacski/tensorflow-serving-arm-client/releases/do
3071
pip install https://github.com/emacski/tensorflow-serving-arm-client/releases/download/2.4.1/tensorflow_serving_arm_client-2.4.1-cp37-none-manylinux2014_aarch64.whl
3172
# on linux_arm python 3.7
3273
pip install https://github.com/emacski/tensorflow-serving-arm-client/releases/download/2.4.1/tensorflow_serving_arm_client-2.4.1-cp37-none-manylinux2014_armv7l.whl
33-
# pure python 3 (will also install grpcio and protobuf pypi packages)
74+
# pure python 3 (will require grpcio and protobuf pypi packages)
3475
pip install https://github.com/emacski/tensorflow-serving-arm-client/releases/download/2.4.1/tensorflow_serving_arm_client-2.4.1-py3-none-any.whl
3576
```
3677

@@ -43,14 +84,66 @@ cd tensorflow-serving-arm-client
4384
docker run --rm -ti \
4485
-w /tensorflow-serving-arm-client \
4586
-v $PWD:/tensorflow-serving-arm-client \
46-
emacski/tensorflow-serving:latest-devel /bin/bash
87+
emacski/tensorflow-serving-arm-client:latest-devel /bin/bash
4788
```
4889
By default, wheel artifacts will be output to the workspace root
4990
```sh
5091
# pure python
5192
bazel run //py/wheel:build_pure
52-
# with extension
93+
# with platform specific deps
5394
bazel run //py/wheel:build_platform --config=linux_amd64
5495
bazel run //py/wheel:build_platform --config=linux_arm64
5596
bazel run //py/wheel:build_platform --config=linux_arm
5697
```
98+
99+
[Back to Top](#contents)
100+
101+
## Client Examples
102+
103+
The client examples are designed to query the same model in the official tensorflow serving example
104+
[TensorFlow Serving with Docker](https://www.tensorflow.org/tfx/serving/docker) using the predict API.
105+
106+
### Model Server Example
107+
Reference instructions for setting up [TensorFlow Serving with Docker](https://www.tensorflow.org/tfx/serving/docker),
108+
substituting the `docker run` command for the one below:
109+
```sh
110+
# this version includes the addition of mapping the grpc port (8500) to the host
111+
docker run -t --rm -p 8501:8501 -p 8500:8500 \
112+
-v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \
113+
-e MODEL_NAME=half_plus_two \
114+
tensorflow/serving &
115+
```
116+
117+
### gRPC Client Examples
118+
```sh
119+
git clone git@github.com:emacski/tensorflow-serving-arm-client.git
120+
cd tensorflow-serving-arm-client
121+
# devel env image includes all deps to build and run examples
122+
docker run --rm -ti \
123+
-w /tensorflow-serving-arm-client \
124+
-v $PWD:/tensorflow-serving-arm-client \
125+
emacski/tensorflow-serving-arm-client:latest-devel /bin/bash
126+
127+
# client examples accept exactly one command-line argument in the form of:
128+
# <model_server_host>:<model_server_port>
129+
130+
# python
131+
bazel run //py/example:half_plus_two -- host.docker.internal:8500
132+
# or
133+
bazel build //py/example:half_plus_two
134+
./bazel-bin/py/example/half_plus_two host.docker.internal:8500
135+
136+
# cc
137+
bazel run //cc/example:half_plus_two -- host.docker.internal:8500
138+
# or
139+
bazel build //cc/example:half_plus_two
140+
./bazel-bin/cc/example/half_plus_two host.docker.internal:8500
141+
142+
# go
143+
bazel run //go/example:half_plus_two -- host.docker.internal:8500
144+
# or
145+
bazel build //go/example:half_plus_two
146+
./bazel-bin/go/example/half_plus_two host.docker.internal:8500
147+
```
148+
149+
[Back to Top](#contents)

WORKSPACE

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
1818

1919
http_archive(
2020
name = "com_github_emacski_bazeltools",
21-
sha256 = "ac040d00f7f00c9947d61c7b8970a877d907c92e088966c24a0eaeeba5551b19",
22-
strip_prefix = "bazel-tools-250e4a98908fa0c6631ebccdeae930a60fd4c0d5",
23-
urls = ["https://github.com/emacski/bazel-tools/archive/250e4a98908fa0c6631ebccdeae930a60fd4c0d5.tar.gz"],
21+
sha256 = "ef868ef493a8fc9609a32093a90b57f320646fa5af3b3eb49bb7380f5e0580c6",
22+
strip_prefix = "bazel-tools-9cbf59fc288489ab3c7e42ed124507e1b1adba3a",
23+
urls = ["https://github.com/emacski/bazel-tools/archive/9cbf59fc288489ab3c7e42ed124507e1b1adba3a.tar.gz"],
2424
)
2525

2626
register_toolchains("@com_github_emacski_bazeltools//toolchain/cpp/clang:all")

cc/README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
C++ Client
2+
==========
3+
4+
## Bazel Workspace
5+
6+
`WORKSPACE` Dependencies
7+
```python
8+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
9+
10+
http_archive(
11+
name = "com_github_emacski_bazeltools",
12+
sha256 = "ef868ef493a8fc9609a32093a90b57f320646fa5af3b3eb49bb7380f5e0580c6",
13+
strip_prefix = "bazel-tools-9cbf59fc288489ab3c7e42ed124507e1b1adba3a",
14+
urls = ["https://github.com/emacski/bazel-tools/archive/9cbf59fc288489ab3c7e42ed124507e1b1adba3a.tar.gz"],
15+
)
16+
17+
# OPTIONAL: only required if using the cross-build cc toolchain
18+
register_toolchains("@com_github_emacski_bazeltools//toolchain/cpp/clang:all")
19+
20+
http_archive(
21+
name = "com_github_emacski_tensorflowservingarmclient",
22+
sha256 = "[BAZEL_HTTP_ARCHIVE_SHA]",
23+
strip_prefix = "tensorflow-serving-arm-client-[GIT_COMMIT_SHA]",
24+
urls = ["https://github.com/emacski/tensorflow-serving-arm-client/archive/[GIT_COMMIT_SHA].tar.gz"],
25+
)
26+
27+
http_archive(
28+
name = "com_github_grpc_grpc",
29+
sha256 = "bb6de0544adddd54662ba1c314eff974e84c955c39204a4a2b733ccd990354b7",
30+
strip_prefix = "grpc-1.36.3",
31+
urls = ["https://github.com/grpc/grpc/archive/v1.36.3.tar.gz"],
32+
)
33+
34+
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
35+
36+
grpc_deps()
37+
38+
load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps")
39+
40+
grpc_extra_deps()
41+
```
42+
43+
Bazel Build Options
44+
```sh
45+
# grpc
46+
--define=grpc_no_ares=true
47+
```
48+
49+
Optional Bazel Build Options
50+
(only required if using the cross-build cc toolchain)
51+
```sh
52+
# enable proper toolchain resolution
53+
--incompatible_enable_cc_toolchain_resolution
54+
55+
# amd64 (x86_64)
56+
--platforms=@com_github_emacski_bazeltools//platform:linux_amd64
57+
# some deps still require legacy toolchain resolution
58+
--crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
59+
--cpu=k8
60+
61+
# arm64 (aarch64)
62+
--platforms=@com_github_emacski_bazeltools//platform:linux_arm64
63+
# some deps still require legacy toolchain resolution
64+
--crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
65+
--cpu=aarch64
66+
67+
# arm (armhf)
68+
--platforms=@com_github_emacski_bazeltools//platform:linux_arm
69+
# some deps still require legacy toolchain resolution
70+
--crosstool_top=@com_github_emacski_bazeltools//toolchain/cpp/clang:toolchain
71+
--cpu=arm
72+
```

cc/example/BUILD

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright 2021 Erik Maciejewski
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
16+
17+
cc_binary(
18+
name = "half_plus_two",
19+
deps = [":half_plus_two_library"],
20+
)
21+
22+
cc_library(
23+
name = "half_plus_two_library",
24+
srcs = ["half_plus_two.cc"],
25+
deps = [
26+
"@com_github_emacski_tensorflowservingarmclient//cc:tensorflow_serving",
27+
],
28+
)

cc/example/half_plus_two.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2021 Erik Maciejewski
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <iostream>
16+
#include <string>
17+
#include <vector>
18+
19+
#include "grpcpp/grpcpp.h"
20+
#include "tensorflow/core/framework/types.pb.h"
21+
#include "tensorflow/core/framework/tensor.pb.h"
22+
#include "tensorflow_serving/apis/prediction_service.grpc.pb.h"
23+
24+
using namespace tensorflow::serving;
25+
26+
int main(int argc, char* argv[]) {
27+
if (argc != 2) {
28+
std::cout << "error: only 1 argument accepted" << std::endl;
29+
return 1;
30+
}
31+
32+
const std::string server_host_port = argv[1];
33+
34+
std::unique_ptr<PredictionService::Stub> stub;
35+
stub = PredictionService::NewStub(grpc::CreateChannel(
36+
server_host_port, grpc::InsecureChannelCredentials()));
37+
38+
// same example inputs from https://www.tensorflow.org/tfx/serving/docker
39+
std::vector<float> inputs = {1.0, 2.0, 5.0};
40+
41+
std::unique_ptr<tensorflow::TensorProto> input_tensor;
42+
input_tensor = std::make_unique<tensorflow::TensorProto>();
43+
44+
input_tensor->mutable_tensor_shape()->add_dim()->set_size(inputs.size());
45+
input_tensor->set_dtype(tensorflow::DataType::DT_FLOAT);
46+
47+
for (auto i = inputs.begin(); i != inputs.end(); i++) {
48+
input_tensor->add_float_val(*i);
49+
}
50+
51+
std::unique_ptr<PredictRequest> req = std::make_unique<PredictRequest>();
52+
53+
req->mutable_model_spec()->set_name("half_plus_two");
54+
req->mutable_model_spec()->set_signature_name("serving_default");
55+
(*req->mutable_inputs())["x"] = *input_tensor;
56+
57+
PredictResponse res;
58+
grpc::ClientContext ctx;
59+
60+
grpc::Status status = stub->Predict(&ctx, *req, &res);
61+
62+
if (status.ok()) {
63+
std::cout << res.DebugString() << std::endl;
64+
} else {
65+
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
66+
}
67+
68+
return 0;
69+
}

0 commit comments

Comments
 (0)