Skip to content

Commit 05feb31

Browse files
Lakshmandhschall
authored andcommitted
Added files for rnn-serving benchmark.
Signed-off-by: L Lakshmanan <[email protected]>
1 parent 42b2444 commit 05feb31

File tree

10 files changed

+362
-3
lines changed

10 files changed

+362
-3
lines changed

.github/workflows/e2e-rnn-serving.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,11 @@ jobs:
175175
if: ${{ always() }}
176176
run: |
177177
set -x
178-
container_list=$(kubectl get pods -n default -o jsonpath="{.items[*].spec.containers[*].name}")
179-
for container_name in $container_list
178+
179+
pod_list=$(kubectl get pods -n default -o jsonpath="{.items[*].name}")
180+
for pod in $pod_list
180181
do
181-
kubectl logs -n default -c $container_name -l serving.knative.dev/service=${{ matrix.service }}
182+
kubectl logs $pod
182183
done
183184
184185
- name: Down

benchmarks/rnn-serving/Makefile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# MIT License
2+
3+
# Copyright (c) 2024 EASE lab
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
ROOT = ../../
24+
25+
all-image: rnn-serving-python
26+
27+
rnn-serving-python: docker/Dockerfile python/server.py python/rnn.py python/requirements.txt model/rnn_model.pth
28+
DOCKER_BUILDKIT=1 docker build \
29+
--tag vhiveease/rnn-serving-python:latest \
30+
--target rnnServingPython \
31+
-f docker/Dockerfile \
32+
$(ROOT) --load
33+
34+
## Push images
35+
push:
36+
docker push docker.io/vhiveease/rnn-serving-python:latest
37+
38+
## Pull images from docker hub
39+
pull:
40+
docker pull docker.io/vhiveease/rnn-serving-python:latest
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# MIT License
2+
3+
# Copyright (c) 2024 EASE lab
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
#---------- PYTHON -----------#
24+
# First stage (Builder):
25+
# Install gRPC and all other dependencies
26+
FROM vhiveease/python-slim:latest as rnnServingPythonBuilder
27+
WORKDIR /py
28+
COPY ./benchmarks/rnn-serving/python/requirements.txt ./requirements.txt
29+
RUN pip3 install --user -r requirements.txt
30+
COPY ./utils/tracing/python/tracing.py ./
31+
COPY ./benchmarks/rnn-serving/python/server.py ./
32+
COPY ./benchmarks/rnn-serving/python/rnn.py ./
33+
ADD https://raw.githubusercontent.com/vhive-serverless/vSwarm-proto/main/proto/rnn_serving/rnn_serving_pb2_grpc.py ./
34+
ADD https://raw.githubusercontent.com/vhive-serverless/vSwarm-proto/main/proto/rnn_serving/rnn_serving_pb2.py ./proto/rnn_serving/
35+
36+
# Second stage (Runner):
37+
FROM vhiveease/python-slim:latest as rnnServingPython
38+
COPY --from=rnnServingPythonBuilder /root/.local /root/.local
39+
COPY --from=rnnServingPythonBuilder /py /app
40+
COPY ./benchmarks/rnn-serving/model/ /app/model
41+
WORKDIR /app
42+
# ENV PATH=/root/.local/bin:$PATH
43+
ENTRYPOINT [ "python3", "/app/server.py" ]
195 KB
Binary file not shown.
403 Bytes
Binary file not shown.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
numpy
2+
torch
3+
grpcio==1.45.0
4+
grpcio-tools==1.45.0
5+
opentelemetry-api==1.3.0
6+
opentelemetry-exporter-zipkin==1.3.0
7+
opentelemetry-exporter-zipkin-json==1.3.0
8+
opentelemetry-exporter-zipkin-proto-http==1.3.0
9+
opentelemetry-instrumentation==0.22b0
10+
opentelemetry-instrumentation-grpc==0.22b0
11+
opentelemetry-sdk==1.3.0
12+
opentelemetry-semantic-conventions==0.22b0
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import torch
2+
import torch.nn as nn
3+
from torch.autograd import Variable
4+
5+
6+
class RNN(nn.Module):
7+
def __init__(self, input_size, hidden_size, output_size, all_categories, n_categories, all_letters, n_letters):
8+
super(RNN, self).__init__()
9+
self.hidden_size = hidden_size
10+
11+
self.all_categories = all_categories
12+
self.n_categories = n_categories
13+
self.all_letters = all_letters
14+
self.n_letters = n_letters
15+
16+
self.i2h = nn.Linear(n_categories + input_size + hidden_size, hidden_size)
17+
self.i2o = nn.Linear(n_categories + input_size + hidden_size, output_size)
18+
self.o2o = nn.Linear(hidden_size + output_size, output_size)
19+
self.dropout = nn.Dropout(0.1)
20+
self.softmax = nn.LogSoftmax(dim=1)
21+
22+
def forward(self, category, input_tensor, hidden):
23+
input_combined = torch.cat((category, input_tensor, hidden), 1)
24+
hidden = self.i2h(input_combined)
25+
output = self.i2o(input_combined)
26+
output_combined = torch.cat((hidden, output), 1)
27+
output = self.o2o(output_combined)
28+
output = self.dropout(output)
29+
output = self.softmax(output)
30+
return output, hidden
31+
32+
def init_hidden(self):
33+
return Variable(torch.zeros(1, self.hidden_size))
34+
35+
@staticmethod
36+
def gen_input_tensor(all_letters, n_letters, line):
37+
tensor = torch.zeros(len(line), 1, n_letters)
38+
for li in range(len(line)):
39+
letter = line[li]
40+
tensor[li][0][all_letters.find(letter)] = 1
41+
return tensor
42+
43+
@staticmethod
44+
def gen_category_tensor(all_categories, n_categories, category):
45+
li = all_categories.index(category)
46+
tensor = torch.zeros(1, n_categories)
47+
tensor[0][li] = 1
48+
return tensor
49+
50+
# Sample from a category and starting letter
51+
def sample(self, category, start_letter='A'):
52+
category_tensor = Variable(self.gen_category_tensor(self.all_categories, self.n_categories, category))
53+
input_tensor = Variable(self.gen_input_tensor(self.all_letters, self.n_letters, start_letter))
54+
hidden = self.init_hidden()
55+
56+
output_name = start_letter
57+
58+
max_length = 20
59+
for i in range(max_length):
60+
output, hidden = self.forward(category_tensor, input_tensor[0], hidden)
61+
topv, topi = output.data.topk(1)
62+
topi = topi[0][0]
63+
64+
if topi == self.n_letters - 1:
65+
break
66+
else:
67+
letter = self.all_letters[topi]
68+
output_name += letter
69+
70+
input_tensor = Variable(self.gen_input_tensor(self.all_letters, self.n_letters, letter))
71+
72+
return output_name
73+
74+
# Get multiple samples from one category and multiple starting letters
75+
def samples(self, category, start_letters='ABC'):
76+
for start_letter in start_letters:
77+
yield self.sample(category, start_letter)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import os
2+
import sys
3+
4+
import pickle
5+
import numpy as np
6+
import torch
7+
import rnn
8+
import string
9+
import random
10+
11+
import tracing
12+
13+
import grpc
14+
import argparse
15+
16+
from proto.rnn_serving import rnn_serving_pb2
17+
import rnn_serving_pb2_grpc
18+
19+
from concurrent import futures
20+
21+
parser = argparse.ArgumentParser()
22+
parser.add_argument("-a", "--addr", dest="addr", default="0.0.0.0", help="IP address")
23+
parser.add_argument("-p", "--port", dest="port", default="50051", help="serve port")
24+
parser.add_argument("-zipkin", "--zipkin", dest="url", default="http://0.0.0.0:9411/api/v2/spans", help="Zipkin endpoint url")
25+
parser.add_argument("--default_language", default="French", help="Default Language in which string will be generated")
26+
parser.add_argument("--num_strings", default=3, help="Number of strings to be generated")
27+
28+
args = parser.parse_args()
29+
args.num_strings = int(args.num_strings)
30+
31+
torch.set_num_threads(1)
32+
33+
rnn_model_path = "model/rnn_model.pth"
34+
35+
all_categories =['French', 'Czech', 'Dutch', 'Polish', 'Scottish', 'Chinese', 'English', 'Italian', 'Portuguese', 'Japanese', 'German', 'Russian', 'Korean', 'Arabic', 'Greek', 'Vietnamese', 'Spanish', 'Irish']
36+
n_categories = len(all_categories)
37+
all_letters = string.ascii_letters + " .,;'-"
38+
n_letters = len(all_letters) + 1
39+
40+
rnn_model = rnn.RNN(n_letters, 128, n_letters, all_categories, n_categories, all_letters, n_letters)
41+
rnn_model.load_state_dict(torch.load(rnn_model_path))
42+
rnn_model.eval()
43+
44+
all_start_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
45+
46+
if tracing.IsTracingEnabled():
47+
tracing.initTracer("rnn-serving-python", url=args.url)
48+
tracing.grpcInstrumentClient()
49+
tracing.grpcInstrumentServer()
50+
51+
def GenerateStringThroughRNN(language, num_strings):
52+
try:
53+
start_letters = "".join(random.choices(all_start_letters, k=num_strings))
54+
output_names = list(rnn_model.samples(language, start_letters))
55+
return f"fn: RNN-Serving | language:{language}.n:{num_strings} | output:{output_names} | runtime: Python"
56+
except Exception as e:
57+
return f"fn: RNN-Serving | language:{language}.n:{num_strings} | RNNServingFailed.Error:{e} | runtime: Python"
58+
59+
class RNNServing(rnn_serving_pb2_grpc.RNNServingServicer):
60+
def GenerateString(self, request, context):
61+
62+
if request.language not in all_categories:
63+
language = args.default_language
64+
else:
65+
language = request.language
66+
67+
if request.numSamples <= 0:
68+
num_strings = args.num_strings
69+
else:
70+
num_strings = request.numSamples
71+
72+
msg = GenerateStringThroughRNN(language, num_strings)
73+
return rnn_serving_pb2.GetString(message=msg)
74+
75+
def serve():
76+
server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
77+
rnn_serving_pb2_grpc.add_RNNServingServicer_to_server(RNNServing(), server)
78+
address = (args.addr + ":" + args.port)
79+
server.add_insecure_port(address)
80+
print("Start RNNServing-python server. Addr: " + address)
81+
server.start()
82+
server.wait_for_termination()
83+
84+
if __name__ == '__main__':
85+
serve()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# MIT License
2+
3+
# Copyright (c) 2024 EASE lab
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
version: "3.3"
24+
services:
25+
rnn-serving-python:
26+
image: vhiveease/rnn-serving-python:latest
27+
container_name: rnn-serving-python
28+
entrypoint:
29+
- python
30+
- /app/server.py
31+
- --addr=0.0.0.0
32+
- --port=50051
33+
- --default_language=French
34+
- --num_strings=15
35+
ports:
36+
- target: 50051
37+
relay:
38+
image: vhiveease/relay:latest
39+
entrypoint:
40+
- /app/server
41+
- --addr=0.0.0.0:50000
42+
- --function-endpoint-url=rnn-serving-python
43+
- --function-endpoint-port=50051
44+
- --function-name=rnn-serving-python
45+
- --value=French
46+
- --generator=random
47+
- --lowerBound=10
48+
- --upperBound=15
49+
ports:
50+
- published: 50000
51+
target: 50000
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# MIT License
2+
3+
# Copyright (c) 2024 EASE lab
4+
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
apiVersion: serving.knative.dev/v1
24+
kind: Service
25+
metadata:
26+
name: rnn-serving-python
27+
namespace: default
28+
spec:
29+
template:
30+
spec:
31+
containers:
32+
- image: docker.io/vhiveease/relay:latest
33+
ports:
34+
- name: h2c
35+
containerPort: 50000
36+
args:
37+
- --addr=0.0.0.0:50000
38+
- --function-endpoint-url=0.0.0.0
39+
- --function-endpoint-port=50051
40+
- --function-name=rnn-serving-python
41+
- --value=French
42+
- --generator=random
43+
- --lowerBound=10
44+
- --upperBound=20
45+
- image: docker.io/vhiveease/rnn-serving-python:latest
46+
args:
47+
- --addr=0.0.0.0
48+
- --port=50051
49+
- --default_language=French
50+
- --num_strings=15

0 commit comments

Comments
 (0)