[demos] Update tf serving example with resnet model
This commit is contained in:
		
							parent
							
								
									6cb368fbbe
								
							
						
					
					
						commit
						91dd93d9a4
					
				| @ -55,9 +55,9 @@ Now users could send inference request with server certificates (`server.crt`). | ||||
| 
 | ||||
| There are prebuilt docker images could be used for the examples, either in the following docker way or [`kubernates`](./kubernetes/) way. Users could pull them directly and try the example. | ||||
| ``` | ||||
| docker pull occlum/init_ra_server:0.29.2-ubuntu20.04 | ||||
| docker pull occlum/tf_demo:0.29.2-ubuntu20.04 | ||||
| docker pull occlum/tf_demo_client:0.29.2-ubuntu20.04 | ||||
| docker pull occlum/init_ra_server:0.29.5-ubuntu20.04 | ||||
| docker pull occlum/tf_demo:0.29.5-ubuntu20.04 | ||||
| docker pull occlum/tf_demo_client:0.29.5-ubuntu20.04 | ||||
| ``` | ||||
| 
 | ||||
| If users want to build or customize the images, please check below part. | ||||
| @ -66,11 +66,11 @@ If users want to build or customize the images, please check below part. | ||||
| 
 | ||||
| Our target is to deploy the demo in separated container images, so docker build is necessary steps. Thanks to the `docker run in docker` method, this example build could be done in Occlum development container image. | ||||
| 
 | ||||
| First, please make sure `docker` is installed successfully in your host. Then start the Occlum container (use version `0.29.2-ubuntu20.04` for example) as below. | ||||
| First, please make sure `docker` is installed successfully in your host. Then start the Occlum container (use version `latest-ubuntu20.04` for example) as below. | ||||
| ``` | ||||
| $ sudo docker run --rm -itd --network host \ | ||||
|         -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock \ | ||||
|         occlum/occlum:0.29.2-ubuntu20.04 | ||||
|         occlum/occlum:latest-ubuntu20.04 | ||||
| ``` | ||||
| 
 | ||||
| All the following are running in the above container. | ||||
| @ -101,7 +101,7 @@ For the tensorflow-serving, there is no need rebuild from source, just use the o | ||||
| Once all content ready, runtime container images build are good to go. | ||||
| This step builds two container images, `init_ra_server` and `tf_demo`. | ||||
| ``` | ||||
| # ./build_container_images.sh <registry> | ||||
| # ./build_container_images.sh <registry> <tag> | ||||
| ``` | ||||
| 
 | ||||
| `<registry>` means the docker registry prefix for the generated container images. | ||||
| @ -128,12 +128,13 @@ usage: run_container.sh [OPTION]... | ||||
|     -p <GRPC Server port> default 50051. | ||||
|     -u <PCCS URL> default https://localhost:8081/sgx/certification/v3/. | ||||
|     -r <registry prefix> the registry for this demo container images. | ||||
|     -g <image tag> the container images tag, default it is "latest". | ||||
|     -h <usage> usage help | ||||
| ``` | ||||
| 
 | ||||
| For example, using PCCS service from aliyun. | ||||
| ``` | ||||
| $ sudo ./run_container.sh -s  localhost -p 50051 -u https://sgx-dcap-server.cn-shanghai.aliyuncs.com/sgx/certification/v3/ -r demo | ||||
| $ sudo ./run_container.sh -s  localhost -p 50051 -u https://sgx-dcap-server.cn-shanghai.aliyuncs.com/sgx/certification/v3/ -r demo -g <tag> | ||||
| ``` | ||||
| 
 | ||||
| If everything goes well, the tensorflow serving service would be available by GRPC secure channel `localhost:9000`. | ||||
| @ -142,12 +143,20 @@ If everything goes well, the tensorflow serving service would be available by GR | ||||
| 
 | ||||
| There is an example python based [`inference client`](./client/inception_client.py) which sends a picture to tensorflow serving service to do inference with previously generated server certificate. | ||||
| 
 | ||||
| Install the dependent python packages. | ||||
| ``` | ||||
| # pip3 install -r client/requirements.txt | ||||
| ``` | ||||
| 
 | ||||
| Start the inference request. | ||||
| ``` | ||||
| # cd client | ||||
| # python3 inception_client.py --server=localhost:9000 --crt ../ssl_configure/server.crt --image cat.jpg | ||||
| # python3 resnet_client_grpc.py --server=localhost:9000 --crt ../ssl_configure/server.crt --image cat.jpg | ||||
| ``` | ||||
| 
 | ||||
| If everything goes well, you will get the most likely predication class (int value, mapping could be found on https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt) and its probability. | ||||
| 
 | ||||
| Or you can use the demo client container image to do the inference test. | ||||
| ``` | ||||
| $ docker run --rm --network host <registry>/tf_demo_client:<tag> python3 inception_client.py --server=localhost:9000 --crt server.crt --image cat.jpg | ||||
| $ docker run --rm --network host <registry>/tf_demo_client:<tag> python3 resnet_client_grpc.py --server=localhost:9000 --crt server.crt --image cat.jpg | ||||
| ``` | ||||
|  | ||||
| @ -27,10 +27,11 @@ function build_tf_serving() | ||||
|     # Dump tensorflow/serving container rootfs content | ||||
|     ./dump_rootfs.sh -i tensorflow/serving -d ${TF_DIR} -g 2.5.1 | ||||
|     pushd ${TF_DIR} | ||||
|     # Download pretrained inception model | ||||
|     rm -rf INCEPTION* | ||||
|     curl -O https://s3-us-west-2.amazonaws.com/tf-test-models/INCEPTION.zip | ||||
|     unzip INCEPTION.zip | ||||
|     # Download pretrained resnet model | ||||
|     rm -rf resnet* | ||||
|     wget https://tfhub.dev/tensorflow/resnet_50/classification/1?tf-hub-format=compressed -O resnet.tar.gz | ||||
|     mkdir -p resnet/123 | ||||
|     tar zxf resnet.tar.gz -C resnet/123 | ||||
|     popd | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| import grpc | ||||
| import tensorflow as tf | ||||
| import argparse, time, grpc, asyncio | ||||
| import numpy as np | ||||
| from PIL import Image | ||||
| 
 | ||||
| from tensorflow_serving.apis import predict_pb2 | ||||
| from tensorflow_serving.apis import prediction_service_pb2_grpc | ||||
| @ -22,17 +24,22 @@ class benchmark_engine(object): | ||||
|     def __prepare__(self): | ||||
|         for idx in range(self.concurrent_num): | ||||
|             # get image array | ||||
|             with open(self.image, 'rb') as f: | ||||
|                 input_name = 'images' | ||||
|                 input_shape = [1] | ||||
|                 input_data = f.read() | ||||
|             # with open(self.image, 'rb') as f: | ||||
|             #     input_name = 'images' | ||||
|             #     input_shape = [1] | ||||
|             #     input_data = f.read() | ||||
| 
 | ||||
|             # Load the image and convert to RGB | ||||
|             img = Image.open(self.image).convert('RGB') | ||||
|             img = img.resize((224,224), Image.BICUBIC) | ||||
|             img_array = np.array(img) | ||||
|             img_array = img_array.astype(np.float32) /255.0 | ||||
|             # create request | ||||
|             request = predict_pb2.PredictRequest() | ||||
|             request.model_spec.name = 'INCEPTION' | ||||
|             request.model_spec.signature_name = 'predict_images' | ||||
|             request.inputs[input_name].CopyFrom( | ||||
|                 tf.make_tensor_proto(input_data, shape=input_shape)) | ||||
|             request.model_spec.name = 'resnet' | ||||
|             request.model_spec.signature_name = 'serving_default' | ||||
|             request.inputs['input_1'].CopyFrom( | ||||
|                 tf.make_tensor_proto(img_array, shape=[1,224,224,3])) | ||||
|              | ||||
|             self.request_signatures.append(request) | ||||
|         return None | ||||
|  | ||||
| @ -1,42 +0,0 @@ | ||||
| import grpc | ||||
| import tensorflow as tf | ||||
| import argparse | ||||
| 
 | ||||
| from tensorflow_serving.apis import predict_pb2 | ||||
| from tensorflow_serving.apis import prediction_service_pb2_grpc | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|   with open(args.crt, 'rb') as f: | ||||
|     creds = grpc.ssl_channel_credentials(f.read()) | ||||
|   channel = grpc.secure_channel(args.server, creds) | ||||
|   stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) | ||||
|   # Send request | ||||
|   with open(args.image, 'rb') as f: | ||||
|     # See prediction_service.proto for gRPC request/response details. | ||||
|     request = predict_pb2.PredictRequest() | ||||
|     request.model_spec.name = 'INCEPTION' | ||||
|     request.model_spec.signature_name = 'predict_images' | ||||
| 
 | ||||
|     input_name = 'images' | ||||
|     input_shape = [1] | ||||
|     input_data = f.read() | ||||
|     request.inputs[input_name].CopyFrom( | ||||
|       tf.make_tensor_proto(input_data, shape=input_shape)) | ||||
| 
 | ||||
|     result = stub.Predict(request, 10.0)  # 10 secs timeout | ||||
|     print(result) | ||||
| 
 | ||||
|   print("Inception Client Passed") | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|   parser = argparse.ArgumentParser() | ||||
|   parser.add_argument('--server', default='localhost:9000', | ||||
|                       help='Tenforflow Model Server Address') | ||||
|   parser.add_argument('--crt', default=None, type=str, help='TLS certificate file path') | ||||
|   parser.add_argument('--image', default='Siberian_Husky_bi-eyed_Flickr.jpg', | ||||
|                       help='Path to the image') | ||||
|   args = parser.parse_args() | ||||
| 
 | ||||
|   main() | ||||
| @ -1,4 +1,5 @@ | ||||
| grpcio>=1.34.0 | ||||
| aiohttp>=3.7.0 | ||||
| tensorflow>=2.3.0 | ||||
| tensorflow-serving-api>=2.3.0 | ||||
| tensorflow==2.11 | ||||
| tensorflow-serving-api==2.11 | ||||
| Pillow==9.4 | ||||
|  | ||||
							
								
								
									
										48
									
								
								example/client/resnet_client_grpc.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										48
									
								
								example/client/resnet_client_grpc.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| import grpc | ||||
| import tensorflow as tf | ||||
| import argparse | ||||
| import numpy as np | ||||
| from PIL import Image | ||||
| 
 | ||||
| from tensorflow_serving.apis import predict_pb2 | ||||
| from tensorflow_serving.apis import prediction_service_pb2_grpc | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|   with open(args.crt, 'rb') as f: | ||||
|     creds = grpc.ssl_channel_credentials(f.read()) | ||||
|   channel = grpc.secure_channel(args.server, creds) | ||||
|   stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) | ||||
| 
 | ||||
|   # Load the image and convert to RGB | ||||
|   img = Image.open(args.image).convert('RGB') | ||||
|   img = img.resize((224,224), Image.BICUBIC) | ||||
|   img_array = np.array(img) | ||||
|   img_array = img_array.astype(np.float32) /255.0 | ||||
| 
 | ||||
|   # Create a request message for TensorFlow Serving | ||||
|   request = predict_pb2.PredictRequest() | ||||
|   request.model_spec.name = 'resnet' | ||||
|   request.model_spec.signature_name = 'serving_default' | ||||
|   request.inputs['input_1'].CopyFrom( | ||||
|     tf.make_tensor_proto(img_array, shape=[1,224,224,3])) | ||||
| 
 | ||||
|   # Send the request to TensorFlow Serving | ||||
|   result = stub.Predict(request, 10.0) | ||||
| 
 | ||||
|   # Print the predicted class and probability | ||||
|   result = result.outputs['activation_49'].float_val | ||||
|   class_idx = np.argmax(result) | ||||
|   print('Prediction class: ', class_idx) | ||||
|   print('Probability: ', result[int(class_idx)]) | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|   parser = argparse.ArgumentParser() | ||||
|   parser.add_argument('--server', default='localhost:9000', | ||||
|                       help='Tenforflow Model Server Address') | ||||
|   parser.add_argument('--crt', default=None, type=str, help='TLS certificate file path') | ||||
|   parser.add_argument('--image', default='Siberian_Husky_bi-eyed_Flickr.jpg', | ||||
|                       help='Path to the image') | ||||
|   args = parser.parse_args() | ||||
| 
 | ||||
|   main() | ||||
| @ -56,12 +56,12 @@ usage: build.sh [OPTION]... | ||||
| 
 | ||||
| For example, below command generates three container images. | ||||
| ``` | ||||
| # ./build.sh -r demo -g 0.29.2 | ||||
| # ./build.sh -r demo -g 0.29.5 | ||||
| ``` | ||||
| 
 | ||||
| * **`demo/init_ra_server:0.29.2`** acts as key broker pod. | ||||
| * **`demo/tf_demo:0.29.2`** acts as tensorflow serving pod. | ||||
| * **`demo/tf_demo_client:0.29.2`** acts as client. | ||||
| * **`demo/init_ra_server:0.29.5`** acts as key broker pod. | ||||
| * **`demo/tf_demo:0.29.5`** acts as tensorflow serving pod. | ||||
| * **`demo/tf_demo_client:0.29.5`** acts as client. | ||||
| 
 | ||||
| ## How to test | ||||
| 
 | ||||
| @ -110,7 +110,7 @@ In default, only one replica for the tensorflow serving pod. | ||||
| ### Try the inference request | ||||
| 
 | ||||
| ``` | ||||
| $ docker run --rm --network host demo/tf_demo_client:0.29.2 python3 inception_client.py --server=localhost:31001 --crt server.crt --image cat.jpg | ||||
| $ docker run --rm --network host demo/tf_demo_client:0.29.5 python3 resnet_client_grpc.py --server=localhost:31001 --crt server.crt --image cat.jpg | ||||
| ``` | ||||
| 
 | ||||
| If successful, it prints the classification results. | ||||
| @ -120,7 +120,7 @@ If successful, it prints the classification results. | ||||
| Below command can do benchmark test for the tensorflow serving service running in Occlum. | ||||
| 
 | ||||
| ``` | ||||
| $ docker run --rm --network host demo/tf_demo_client:0.29.2 python3 benchmark.py --server localhost:31001 --crt server.crt --cnum 4 --loop 10 --image cat.jpg | ||||
| $ docker run --rm --network host demo/tf_demo_client:0.29.5 python3 benchmark.py --server localhost:31001 --crt server.crt --cnum 4 --loop 10 --image cat.jpg | ||||
| ``` | ||||
| 
 | ||||
| Try scale up the tensorflow serving pods number, better `tps` can be achieved. | ||||
|  | ||||
| @ -29,8 +29,8 @@ spec: | ||||
|         - occlum | ||||
|         - run | ||||
|         - /bin/tensorflow_model_server | ||||
|         - --model_name=INCEPTION | ||||
|         - --model_base_path=/model/INCEPTION/INCEPTION | ||||
|         - --model_name=resnet | ||||
|         - --model_base_path=/models/resnet | ||||
|         - --port=9001 | ||||
|         - --ssl_config_file=/etc/tf_ssl.cfg | ||||
|         ports: | ||||
|  | ||||
| @ -11,12 +11,12 @@ pushd occlum_server | ||||
| occlum run /bin/server ${GRPC_SERVER} & | ||||
| popd | ||||
| 
 | ||||
| sleep 3 | ||||
| sleep 10 | ||||
| 
 | ||||
| echo "Start Tensorflow-Serving on backgound ..." | ||||
| 
 | ||||
| pushd occlum_tf | ||||
| taskset -c 0,1 occlum run /bin/tensorflow_model_server \ | ||||
|         --model_name=INCEPTION --model_base_path=/model/INCEPTION/INCEPTION \ | ||||
|         --model_name=resnet --model_base_path=/models/resnet \ | ||||
|         --port=9000 --ssl_config_file="/etc/tf_ssl.cfg" | ||||
| popd | ||||
|  | ||||
| @ -57,5 +57,5 @@ docker run --network host \ | ||||
|         --env GRPC_SERVER="${GRPC_SERVER}" \ | ||||
|         ${registry}/tf_demo:${tag} \ | ||||
|         taskset -c 0,1 occlum run /bin/tensorflow_model_server \ | ||||
|         --model_name=INCEPTION --model_base_path=/model/INCEPTION/INCEPTION \ | ||||
|         --model_name=resnet --model_base_path=/models/resnet \ | ||||
|         --port=9000 --ssl_config_file="/etc/tf_ssl.cfg" & | ||||
|  | ||||
| @ -2,10 +2,10 @@ includes: | ||||
|   - base.yaml | ||||
| targets: | ||||
|   # copy model | ||||
|   - target: /model | ||||
|   - target: /models | ||||
|     copy:  | ||||
|       - dirs: | ||||
|         - ${TF_DIR}/INCEPTION | ||||
|         - ${TF_DIR}/resnet | ||||
|   - target: /bin | ||||
|     copy:  | ||||
|       - files: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user