From e9f78660d8a3ba4e1d30e4f3c52af4178c6cd5d4 Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Fri, 21 Aug 2020 14:16:10 -0700 Subject: [PATCH] FOR TESTING ONLY: Test with different batch sizes, fix brk size --- .../pytorch/pytorch.manifest.template.ppml | 13 ++++- .../pytorch/pytorch.manifest.template.sgx | 11 +++- Examples/pytorch/pytorchexample.py | 28 ++++----- Examples/pytorch/run-experiment.sh | 57 +++++++++---------- 4 files changed, 57 insertions(+), 52 deletions(-) diff --git a/Examples/pytorch/pytorch.manifest.template.ppml b/Examples/pytorch/pytorch.manifest.template.ppml index 75aee382..516c4a0c 100644 --- a/Examples/pytorch/pytorch.manifest.template.ppml +++ b/Examples/pytorch/pytorch.manifest.template.ppml @@ -19,6 +19,13 @@ loader.debug_type = $(GRAPHENEDEBUG) # Read application arguments directly from the command line. Don't use this on production! loader.insecure__use_cmdline_argv = 1 +# PyTorch may use up to 28GB of RAM in our experiments, so disable ASLR to have more enclave memory +loader.insecure__disable_aslr = 1 + +# PyTorch/Python uses up to 10GB of brk region in our experiments, so set this option. Otherwise, +# expect significant perf degradation since PyTorch falls back to slower mmap/munmap logic. +sys.brk.max_size = 12G + # Environment variables loader.env.LD_LIBRARY_PATH = /lib:/usr/lib:$(ARCH_LIBDIR):/usr/$(ARCH_LIBDIR):./ loader.env.LD_PRELOAD = "libsecret_prov_attest.so /lib/libgomp.so.1" @@ -79,7 +86,7 @@ fs.mount.pip.uri = file:$(HOME)/.local/lib # than the enclave size, Graphene will not be able to allocate it. # # In particular, libtorch*.so is more than 1G, thus 4G is the minimum to make this run. -sgx.enclave_size = 8G +sgx.enclave_size = 32G # Set the maximum number of enclave threads. For SGX v1, the number of enclave # TCSes must be specified during signing, so the application cannot use more @@ -89,7 +96,9 @@ sgx.enclave_size = 8G # the application can create is (sgx.thread_num - 2). # # We (somewhat arbitrarily) specify 128 threads for this workload. -sgx.thread_num = 128 +sgx.thread_num = 176 + +#sgx.rpc_thread_num = 176 # SGX trusted libraries diff --git a/Examples/pytorch/pytorch.manifest.template.sgx b/Examples/pytorch/pytorch.manifest.template.sgx index 97d874d2..80850e2e 100644 --- a/Examples/pytorch/pytorch.manifest.template.sgx +++ b/Examples/pytorch/pytorch.manifest.template.sgx @@ -19,6 +19,13 @@ loader.debug_type = $(GRAPHENEDEBUG) # Read application arguments directly from the command line. Don't use this on production! loader.insecure__use_cmdline_argv = 1 +# PyTorch may use up to 28GB of RAM in our experiments, so disable ASLR to have more enclave memory +loader.insecure__disable_aslr = 1 + +# PyTorch/Python uses up to 10GB of brk region in our experiments, so set this option. Otherwise, +# expect significant perf degradation since PyTorch falls back to slower mmap/munmap logic. +sys.brk.max_size = 12G + # Environment variables loader.env.LD_LIBRARY_PATH = /lib:/usr/lib:$(ARCH_LIBDIR):/usr/$(ARCH_LIBDIR) loader.env.LD_PRELOAD = "/lib/libgomp.so.1" @@ -65,7 +72,7 @@ fs.mount.pip.uri = file:$(HOME)/.local/lib # than the enclave size, Graphene will not be able to allocate it. # # In particular, libtorch*.so is more than 1G, thus 4G is the minimum to make this run. -sgx.enclave_size = 8G +sgx.enclave_size = 32G # Set the maximum number of enclave threads. For SGX v1, the number of enclave # TCSes must be specified during signing, so the application cannot use more @@ -77,6 +84,8 @@ sgx.enclave_size = 8G # We (somewhat arbitrarily) specify 128 threads for this workload. sgx.thread_num = 176 +#sgx.rpc_thread_num = 176 + # SGX trusted libraries sgx.trusted_files.ld = file:$(GRAPHENEDIR)/Runtime/ld-linux-x86-64.so.2 diff --git a/Examples/pytorch/pytorchexample.py b/Examples/pytorch/pytorchexample.py index 04c14b19..fcadfebf 100644 --- a/Examples/pytorch/pytorchexample.py +++ b/Examples/pytorch/pytorchexample.py @@ -1,21 +1,21 @@ # This PyTorch image classification example is based off # https://www.learnopencv.com/pytorch-for-beginners-image-classification-using-pre-trained-models/ from timeit import default_timer as timer +from torchvision import models import statistics import torch -from torchvision import models -torch.set_num_threads(72) +EXP_NUM_THREADS = 1 +EXP_BATCH_SIZE = 1 + +torch.set_num_threads(EXP_NUM_THREADS) -# Load the model from a file start = timer() #alexnet = torch.load("pretrained.pt") alexnet = models.inception_v3(pretrained=True) end = timer() model_load_time = end - start -# Prepare a transform to get the input image into a format (e.g., x,y dimensions) the classifier -# expects. from torchvision import transforms transform = transforms.Compose([ transforms.Resize(256), @@ -26,23 +26,20 @@ transform = transforms.Compose([ std=[0.229, 0.224, 0.225] )]) -# Load the image. from PIL import Image img = Image.open("input.jpg") - -# Apply the transform to the image. img_t = transform(img) - -# Magic (not sure what this does). -batch_t = torch.unsqueeze(img_t, 0) +batch_t = torch.unsqueeze(img_t, 0).repeat(EXP_BATCH_SIZE, 1, 1, 1) alexnet.eval() -for i in range (0,3): +# warmup runs +for i in range (0,10): out = alexnet(batch_t) +# experiment runs sample = [] -for i in range (0,200): +for i in range (0,30): start = timer() out = alexnet(batch_t) end = timer() @@ -50,16 +47,11 @@ for i in range (0,200): print(model_load_time, statistics.mean(sample),statistics.stdev(sample)) -# Load the classes from disk. with open('classes.txt') as f: classes = [line.strip() for line in f.readlines()] -# Sort the predictions. _, indices = torch.sort(out, descending=True) - -# Convert into percentages. percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100 -# Print the 5 most likely predictions. with open("result.txt", "w") as outfile: outfile.write(str([(classes[idx], percentage[idx].item()) for idx in indices[0][:5]])) diff --git a/Examples/pytorch/run-experiment.sh b/Examples/pytorch/run-experiment.sh index 96eb5f4c..3c70b6a1 100755 --- a/Examples/pytorch/run-experiment.sh +++ b/Examples/pytorch/run-experiment.sh @@ -1,6 +1,6 @@ #!/bin/bash -# BEFORE RUNNING THIS: +# BEFORE RUNNING THIS, FOR SGX PPML: # - Build Examples/ra-tls-secret-prov with DCAP and start ./secret_prov_server_dcap # - Build libsecret_prov_attest.so and copy here @@ -9,6 +9,15 @@ set -e SCRIPT=pytorchexample.py STDERRFWD=stderr.log +# batch size of 1 best for latency, batch size of 32 best for throughput; +# we use 32 because higher batch sizes (64, 128) lead to 64GB enclaves and +# are thus too slow for our experiments +sizes=( + 1 + 32 +) + +# experiments performed on 36 physical cores, 72 hyperthreads threads=( 1 2 @@ -25,12 +34,13 @@ threads=( 72 ) +# for experiments, use only 4 most interesting network models networks=( -# alexnet squeezenet1_0 vgg19 wide_resnet50_2 resnet50 +# alexnet # densenet161 # mobilenet_v2 # googlenet @@ -57,57 +67,41 @@ else fi for i in {1..3}; do -for net in "${networks[@]}"; do +for SIZE in "${sizes[@]}"; do +for NETWORK in "${networks[@]}"; do for NUM_THREADS in ${threads[@]}; do - echo "=== $1 $net $i $NUM_THREADS ===" + echo "=== $1 $i $SIZE $NETWORK $NUM_THREADS ===" - # set the number of threads - sed "s/set_num_threads([0-9]*)/set_num_threads($NUM_THREADS)/" -i $SCRIPT + # set the number of threads, batch size, and used model + sed "s/EXP_NUM_THREADS = [0-9]*/EXP_NUM_THREADS = $NUM_THREADS/" -i $SCRIPT + sed "s/EXP_BATCH_SIZE = [0-9]*/EXP_BATCH_SIZE = $SIZE/" -i $SCRIPT + sed "s/models.[a-zA-Z0-9_]*(/models.$NETWORK(/" -i $SCRIPT - # change the python script to switch the model - sed "s/models.[a-zA-Z0-9_]*(/models.$net(/" -i $SCRIPT - - ########################### - # Native # - ########################### - if [ "$1" == "native" ] - then + if [ "$1" == "native" ]; then make clean >/dev/null make SGX=1 >/dev/null OMP_NUM_THREADS=$NUM_THREADS MKL_NUM_THREADS=$NUM_THREADS numactl --cpunodebind=0 --membind=0 \ python3 $SCRIPT fi - ########################### - # Graphene w/o SGX # - ########################### - if [ "$1" == "graphene" ] - then + if [ "$1" == "graphene" ]; then make clean >/dev/null make SGX=1 >/dev/null OMP_NUM_THREADS=$NUM_THREADS MKL_NUM_THREADS=$NUM_THREADS numactl --cpunodebind=0 --membind=0 \ ./pal_loader pytorch.manifest $SCRIPT 2>$STDERRFWD fi - ########################### - # Graphene w/ SGX # - ########################### - if [ "$1" == "sgx" ] - then + if [ "$1" == "sgx" ]; then make clean >/dev/null - NETFILE=$(ls ~/.cache/torch/hub/checkpoints | grep "^$net") + NETFILE=$(ls ~/.cache/torch/hub/checkpoints | grep "^$NETWORK") sed "s/[a-z0-9_-]*\.pth$/$NETFILE/" -i pytorch.manifest.template make SGX=1 >/dev/null SGX=1 OMP_NUM_THREADS=$NUM_THREADS MKL_NUM_THREADS=$NUM_THREADS numactl --cpunodebind=0 --membind=0 \ ./pal_loader pytorch.manifest $SCRIPT 2>$STDERRFWD fi - ########################### - # Graphene w/ SGX + PPML # - ########################### - if [ "$1" == "ppml" ] - then - sed "s/models\.[a-zA-Z0-9_]*(/models\.$net(/" -i download-pretrained-model.py + if [ "$1" == "ppml" ]; then + sed "s/models\.[a-zA-Z0-9_]*(/models\.$NETWORK(/" -i download-pretrained-model.py make clean >/dev/null make download_model >/dev/null LD_LIBRARY_PATH=../ra-tls-secret-prov ../ra-tls-secret-prov/pf_crypt encrypt -w ../ra-tls-secret-prov/files/wrap-key -i ./plaintext/pretrained.pt -o pretrained.pt >/dev/null @@ -120,3 +114,4 @@ for NUM_THREADS in ${threads[@]}; do done done done +done