-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Allow Local Serving of Models in S3 #217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
018d99f
ed659ae
657a045
ee52faa
cd99b71
62b694a
faa9099
768e196
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,12 @@ | |
|
||
import boto3 | ||
import numpy | ||
import pytest | ||
|
||
from sagemaker.local import LocalSession, LocalSagemakerRuntimeClient, LocalSagemakerClient | ||
from sagemaker.mxnet import MXNet | ||
from sagemaker.mxnet import MXNet, MXNetModel | ||
from sagemaker.tensorflow import TensorFlow | ||
from sagemaker.fw_utils import tar_and_upload_dir | ||
from tests.integ import DATA_DIR | ||
from tests.integ.timeout import timeout | ||
|
||
|
@@ -54,6 +56,25 @@ def _initialize(self, boto_session, sagemaker_client, sagemaker_runtime_client): | |
self.local_mode = True | ||
|
||
|
||
@pytest.fixture(scope='module') | ||
def mxnet_model(sagemaker_local_session): | ||
script_path = os.path.join(DATA_DIR, 'mxnet_mnist', 'mnist.py') | ||
data_path = os.path.join(DATA_DIR, 'mxnet_mnist') | ||
|
||
mx = MXNet(entry_point=script_path, role='SageMakerRole', | ||
train_instance_count=1, train_instance_type='local', | ||
sagemaker_session=sagemaker_local_session) | ||
|
||
train_input = mx.sagemaker_session.upload_data(path=os.path.join(data_path, 'train'), | ||
key_prefix='integ-test-data/mxnet_mnist/train') | ||
test_input = mx.sagemaker_session.upload_data(path=os.path.join(data_path, 'test'), | ||
key_prefix='integ-test-data/mxnet_mnist/test') | ||
|
||
mx.fit({'train': train_input, 'test': test_input}) | ||
model = mx.create_model(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the argument necessary here? |
||
return model | ||
|
||
|
||
def test_tf_local_mode(tf_full_version, sagemaker_local_session): | ||
local_mode_lock_fd = open(LOCK_PATH, 'w') | ||
local_mode_lock = local_mode_lock_fd.fileno() | ||
|
@@ -230,6 +251,57 @@ def test_tf_local_data_local_script(): | |
fcntl.lockf(local_mode_lock, fcntl.LOCK_UN) | ||
|
||
|
||
def test_local_mode_serving_from_s3_model(sagemaker_local_session, mxnet_model): | ||
local_mode_lock_fd = open(LOCK_PATH, 'w') | ||
local_mode_lock = local_mode_lock_fd.fileno() | ||
|
||
model_data = mxnet_model.model_data | ||
boto_session = sagemaker_local_session.boto_session | ||
default_bucket = sagemaker_local_session.default_bucket() | ||
uploaded_data = tar_and_upload_dir(boto_session, default_bucket, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only necessary to create the model data, right? In the normal use cases, the user would either do both training and deploy locally, or create the MXNetModel pointing to local model data, or already have an S3 url with model data, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, this is because I wanted to make this faster by training using local mode instead of training on sagemaker like the chainer tests do for instance. |
||
'test_mxnet_local_mode', '', model_data) | ||
|
||
s3_model = MXNetModel(model_data=uploaded_data.s3_prefix, role='SageMakerRole', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is role still necessary here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its not necessary, but the estimators/model expects one. For SageMaker this is a must have, on local mode its not even used but I dont know if we should make this optional. |
||
entry_point=mxnet_model.entry_point, image=mxnet_model.image, | ||
sagemaker_session=sagemaker_local_session) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it necessary to explicitly pass a LocalSession here, or is that only for our tests? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It used to be required, now its only for our tests. |
||
|
||
predictor = None | ||
try: | ||
# Since Local Mode uses the same port for serving, we need a lock in order | ||
# to allow concurrent test execution. The serving test is really fast so it still | ||
# makes sense to allow this behavior. | ||
fcntl.lockf(local_mode_lock, fcntl.LOCK_EX) | ||
predictor = s3_model.deploy(initial_instance_count=1, instance_type='local') | ||
data = numpy.zeros(shape=(1, 1, 28, 28)) | ||
predictor.predict(data) | ||
finally: | ||
if predictor: | ||
predictor.delete_endpoint() | ||
time.sleep(5) | ||
fcntl.lockf(local_mode_lock, fcntl.LOCK_UN) | ||
|
||
|
||
def test_local_mode_serving_from_local_model(sagemaker_local_session, mxnet_model): | ||
local_mode_lock_fd = open(LOCK_PATH, 'w') | ||
local_mode_lock = local_mode_lock_fd.fileno() | ||
predictor = None | ||
|
||
try: | ||
# Since Local Mode uses the same port for serving, we need a lock in order | ||
# to allow concurrent test execution. The serving test is really fast so it still | ||
# makes sense to allow this behavior. | ||
fcntl.lockf(local_mode_lock, fcntl.LOCK_EX) | ||
mxnet_model.sagemaker_session = sagemaker_local_session | ||
predictor = mxnet_model.deploy(initial_instance_count=1, instance_type='local') | ||
data = numpy.zeros(shape=(1, 1, 28, 28)) | ||
predictor.predict(data) | ||
finally: | ||
if predictor: | ||
predictor.delete_endpoint() | ||
time.sleep(5) | ||
fcntl.lockf(local_mode_lock, fcntl.LOCK_UN) | ||
|
||
|
||
def test_mxnet_local_mode(sagemaker_local_session): | ||
local_mode_lock_fd = open(LOCK_PATH, 'w') | ||
local_mode_lock = local_mode_lock_fd.fileno() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the case where this is false?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BYO :) we only have sagemaker_submit_dir on our Frameworks.