Skip to content

Commit 714e569

Browse files
lianyidingChuyang Deng
authored and
Chuyang Deng
committed
making changes for regions without m4 instances. Adding account for HKG. Squash commits.
1 parent 4ac4f98 commit 714e569

34 files changed

+423
-290
lines changed

src/sagemaker/fw_utils.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
UploadedCode = namedtuple("UserCode", ["s3_prefix", "script_name"])
3030
"""sagemaker.fw_utils.UserCode: An object containing the S3 prefix and script name.
31-
3231
This is for the source code used for the entry point with an ``Estimator``. It can be
3332
instantiated with positional or keyword arguments.
3433
"""
@@ -54,6 +53,8 @@
5453
VALID_PY_VERSIONS = ["py2", "py3"]
5554
VALID_EIA_FRAMEWORKS = ["tensorflow", "tensorflow-serving", "mxnet", "mxnet-serving"]
5655
VALID_ACCOUNTS_BY_REGION = {"us-gov-west-1": "246785580436", "us-iso-east-1": "744548109606"}
56+
OPT_IN_ACCOUNTS_BY_REGION = {"ap-east-1": "057415533634"}
57+
ASIMOV_OPT_IN_ACCOUNTS_BY_REGION = {"ap-east-1": "871362719292"}
5758

5859
MERGED_FRAMEWORKS_REPO_MAP = {
5960
"tensorflow-scriptmode": "tensorflow-training",
@@ -73,12 +74,10 @@
7374
def is_version_equal_or_higher(lowest_version, framework_version):
7475
"""Determine whether the ``framework_version`` is equal to or higher than
7576
``lowest_version``
76-
7777
Args:
7878
lowest_version (List[int]): lowest version represented in an integer
7979
list
8080
framework_version (str): framework version string
81-
8281
Returns:
8382
bool: Whether or not framework_version is equal to or higher than
8483
lowest_version
@@ -125,7 +124,11 @@ def _registry_id(region, framework, py_version, account, accelerator_type, frame
125124
framework_version:
126125
"""
127126
if _using_merged_images(region, framework, py_version, accelerator_type, framework_version):
127+
if region in ASIMOV_OPT_IN_ACCOUNTS_BY_REGION:
128+
return ASIMOV_OPT_IN_ACCOUNTS_BY_REGION.get(region)
128129
return "763104351884"
130+
if region in OPT_IN_ACCOUNTS_BY_REGION:
131+
return OPT_IN_ACCOUNTS_BY_REGION.get(region)
129132
return VALID_ACCOUNTS_BY_REGION.get(region, account)
130133

131134

@@ -140,7 +143,6 @@ def create_image_uri(
140143
optimized_families=None,
141144
):
142145
"""Return the ECR URI of an image.
143-
144146
Args:
145147
region (str): AWS region where the image is uploaded.
146148
framework (str): framework used by the image.
@@ -155,7 +157,6 @@ def create_image_uri(
155157
accelerator_type (str): SageMaker Elastic Inference accelerator type.
156158
optimized_families (str): Instance families for which there exist
157159
specific optimized images.
158-
159160
Returns:
160161
str: The appropriate image URI based on the given parameters.
161162
"""
@@ -249,11 +250,9 @@ def _accelerator_type_valid_for_framework(
249250

250251
def validate_source_dir(script, directory):
251252
"""Validate that the source directory exists and it contains the user script
252-
253253
Args:
254254
script (str): Script filename.
255255
directory (str): Directory containing the source file.
256-
257256
Raises:
258257
ValueError: If ``directory`` does not exist, is not a directory, or does
259258
not contain ``script``.
@@ -272,18 +271,14 @@ def tar_and_upload_dir(
272271
):
273272
"""Package source files and upload a compress tar file to S3. The S3
274273
location will be ``s3://<bucket>/s3_key_prefix/sourcedir.tar.gz``.
275-
276274
If directory is an S3 URI, an UploadedCode object will be returned, but
277275
nothing will be uploaded to S3 (this allow reuse of code already in S3).
278-
279276
If directory is None, the script will be added to the archive at
280277
``./<basename of script>``.
281-
282278
If directory is not None, the (recursive) contents of the directory will
283279
be added to the archive. directory is treated as the base path of the
284280
archive, and the script name is assumed to be a filename or relative path
285281
inside the directory.
286-
287282
Args:
288283
session (boto3.Session): Boto session used to access S3.
289284
bucket (str): S3 bucket to which the compressed file is uploaded.
@@ -296,7 +291,6 @@ def tar_and_upload_dir(
296291
copied into /opt/ml/lib
297292
kms_key (str): Optional. KMS key ID used to upload objects to the bucket
298293
(default: None).
299-
300294
Returns:
301295
sagemaker.fw_utils.UserCode: An object with the S3 bucket and key (S3 prefix) and
302296
script name.
@@ -343,7 +337,6 @@ def _list_files_to_compress(script, directory):
343337
def framework_name_from_image(image_name):
344338
# noinspection LongLine
345339
"""Extract the framework and Python version from the image name.
346-
347340
Args:
348341
image_name (str): Image URI, which should be one of the following forms:
349342
legacy:
@@ -354,7 +347,6 @@ def framework_name_from_image(image_name):
354347
'<account>.dkr.ecr.<region>.amazonaws.com/sagemaker-<fw>:<fw_version>-<device>-<py_ver>'
355348
current:
356349
'<account>.dkr.ecr.<region>.amazonaws.com/sagemaker-rl-<fw>:<rl_toolkit><rl_version>-<device>-<py_ver>'
357-
358350
Returns:
359351
tuple: A tuple containing:
360352
str: The framework name str: The Python version str: The image tag
@@ -390,11 +382,9 @@ def framework_name_from_image(image_name):
390382

391383
def framework_version_from_tag(image_tag):
392384
"""Extract the framework version from the image tag.
393-
394385
Args:
395386
image_tag (str): Image tag, which should take the form
396387
'<framework_version>-<device>-<py_version>'
397-
398388
Returns:
399389
str: The framework version.
400390
"""
@@ -406,10 +396,8 @@ def framework_version_from_tag(image_tag):
406396
def parse_s3_url(url):
407397
"""Returns an (s3 bucket, key name/prefix) tuple from a url with an s3
408398
scheme
409-
410399
Args:
411400
url (str):
412-
413401
Returns:
414402
tuple: A tuple containing:
415403
str: S3 bucket name str: S3 key
@@ -422,16 +410,13 @@ def parse_s3_url(url):
422410

423411
def model_code_key_prefix(code_location_key_prefix, model_name, image):
424412
"""Returns the s3 key prefix for uploading code during model deployment
425-
426413
The location returned is a potential concatenation of 2 parts
427414
1. code_location_key_prefix if it exists
428415
2. model_name or a name derived from the image
429-
430416
Args:
431417
code_location_key_prefix (str): the s3 key prefix from code_location
432418
model_name (str): the name of the model
433419
image (str): the image from which a default name can be extracted
434-
435420
Returns:
436421
str: the key prefix to be used in uploading code
437422
"""

tests/conftest.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import boto3
1919
import pytest
20+
import tests.integ
2021
from botocore.config import Config
2122

2223
from sagemaker import Session
@@ -30,6 +31,8 @@
3031

3132
DEFAULT_REGION = "us-west-2"
3233

34+
NO_M4_REGIONS = ["eu-west-3", "eu-north-1", "ap-east-1"]
35+
3336

3437
def pytest_addoption(parser):
3538
parser.addoption("--sagemaker-client-config", action="store", default=None)
@@ -242,3 +245,33 @@ def tf_full_version(request):
242245
@pytest.fixture(scope="module")
243246
def ei_tf_full_version(request):
244247
return request.config.getoption("--ei-tf-full-version")
248+
249+
250+
@pytest.fixture(scope="session")
251+
def cpu_instance_type(sagemaker_session, request):
252+
region = sagemaker_session.boto_session.region_name
253+
if region in NO_M4_REGIONS:
254+
return "ml.m5.xlarge"
255+
else:
256+
return "ml.m4.xlarge"
257+
258+
259+
@pytest.fixture(scope="session")
260+
def cpu_instance_family(cpu_instance_type):
261+
"_".join(cpu_instance_type.split(".")[0:2])
262+
263+
264+
def pytest_generate_tests(metafunc):
265+
if "instance_type" in metafunc.fixturenames:
266+
boto_config = metafunc.config.getoption("--boto-config")
267+
parsed_config = json.loads(boto_config) if boto_config else {}
268+
region = parsed_config.get("region_name", DEFAULT_REGION)
269+
cpu_instance_type = "ml.m5.xlarge" if region in NO_M4_REGIONS else "ml.m4.xlarge"
270+
271+
params = [cpu_instance_type]
272+
if not (
273+
region in tests.integ.HOSTING_NO_P2_REGIONS
274+
or region in tests.integ.TRAINING_NO_P2_REGIONS
275+
):
276+
params.append("ml.p2.xlarge")
277+
metafunc.parametrize("instance_type", params, scope="session")

tests/integ/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@
6868
"ap-northeast-2",
6969
]
7070

71+
NO_LDA_REGIONS = ["eu-west-3", "eu-north-1", "sa-east-1", "ap-east-1"]
72+
NO_MARKET_PLACE_REGIONS = ["eu-west-3", "eu-north-1", "sa-east-1", "ap-east-1"]
73+
7174
logging.getLogger("boto3").setLevel(logging.INFO)
7275
logging.getLogger("botocore").setLevel(logging.INFO)
7376

tests/integ/conftest.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
import os
1616

17-
import pytest
18-
1917

2018
def create_sagemaker_local_network():
2119
"""
@@ -28,8 +26,3 @@ def create_sagemaker_local_network():
2826

2927

3028
create_sagemaker_local_network()
31-
32-
33-
@pytest.fixture(scope="session", params=["local", "ml.c4.xlarge"])
34-
def instance_type(request):
35-
return request.param

tests/integ/marketplace_utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,8 @@
2626
"ca-central-1": "470592106596",
2727
"eu-west-2": "856760150666",
2828
"us-west-1": "382657785993",
29+
"eu-west-3": "843114510376",
30+
"eu-north-1": "136758871317",
31+
"sa-east-1": "270155090741",
32+
"ap-east-1": "822005858737",
2933
}

tests/integ/test_byo_estimator.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def fm_serializer(data):
4141

4242

4343
@pytest.mark.canary_quick
44-
def test_byo_estimator(sagemaker_session, region):
44+
def test_byo_estimator(sagemaker_session, region, cpu_instance_type):
4545
"""Use Factorization Machines algorithm as an example here.
4646
4747
First we need to prepare data for training. We take standard data set, convert it to the
@@ -74,7 +74,7 @@ def test_byo_estimator(sagemaker_session, region):
7474
image_name=image_name,
7575
role="SageMakerRole",
7676
train_instance_count=1,
77-
train_instance_type="ml.c4.xlarge",
77+
train_instance_type=cpu_instance_type,
7878
sagemaker_session=sagemaker_session,
7979
)
8080

@@ -87,7 +87,7 @@ def test_byo_estimator(sagemaker_session, region):
8787

8888
with timeout_and_delete_endpoint_by_name(job_name, sagemaker_session):
8989
model = estimator.create_model()
90-
predictor = model.deploy(1, "ml.m4.xlarge", endpoint_name=job_name)
90+
predictor = model.deploy(1, cpu_instance_type, endpoint_name=job_name)
9191
predictor.serializer = fm_serializer
9292
predictor.content_type = "application/json"
9393
predictor.deserializer = sagemaker.predictor.json_deserializer
@@ -99,7 +99,7 @@ def test_byo_estimator(sagemaker_session, region):
9999
assert prediction["score"] is not None
100100

101101

102-
def test_async_byo_estimator(sagemaker_session, region):
102+
def test_async_byo_estimator(sagemaker_session, region, cpu_instance_type):
103103
image_name = registry(region) + "/factorization-machines:1"
104104
endpoint_name = unique_name_from_base("byo")
105105
training_data_path = os.path.join(DATA_DIR, "dummy_tensor")
@@ -123,7 +123,7 @@ def test_async_byo_estimator(sagemaker_session, region):
123123
image_name=image_name,
124124
role="SageMakerRole",
125125
train_instance_count=1,
126-
train_instance_type="ml.c4.xlarge",
126+
train_instance_type=cpu_instance_type,
127127
sagemaker_session=sagemaker_session,
128128
)
129129

@@ -139,7 +139,7 @@ def test_async_byo_estimator(sagemaker_session, region):
139139
training_job_name=job_name, sagemaker_session=sagemaker_session
140140
)
141141
model = estimator.create_model()
142-
predictor = model.deploy(1, "ml.m4.xlarge", endpoint_name=endpoint_name)
142+
predictor = model.deploy(1, cpu_instance_type, endpoint_name=endpoint_name)
143143
predictor.serializer = fm_serializer
144144
predictor.content_type = "application/json"
145145
predictor.deserializer = sagemaker.predictor.json_deserializer

tests/integ/test_chainer_train.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_training_with_additional_hyperparameters(sagemaker_local_session, chain
6262

6363
@pytest.mark.canary_quick
6464
@pytest.mark.regional_testing
65-
def test_attach_deploy(sagemaker_session, chainer_full_version):
65+
def test_attach_deploy(sagemaker_session, chainer_full_version, cpu_instance_type):
6666
with timeout(minutes=TRAINING_DEFAULT_TIMEOUT_MINUTES):
6767
script_path = os.path.join(DATA_DIR, "chainer_mnist", "mnist.py")
6868
data_path = os.path.join(DATA_DIR, "chainer_mnist")
@@ -73,7 +73,7 @@ def test_attach_deploy(sagemaker_session, chainer_full_version):
7373
framework_version=chainer_full_version,
7474
py_version=PYTHON_VERSION,
7575
train_instance_count=1,
76-
train_instance_type="ml.c4.xlarge",
76+
train_instance_type=cpu_instance_type,
7777
sagemaker_session=sagemaker_session,
7878
hyperparameters={"epochs": 1},
7979
)
@@ -95,7 +95,7 @@ def test_attach_deploy(sagemaker_session, chainer_full_version):
9595
estimator = Chainer.attach(
9696
chainer.latest_training_job.name, sagemaker_session=sagemaker_session
9797
)
98-
predictor = estimator.deploy(1, "ml.m4.xlarge", endpoint_name=endpoint_name)
98+
predictor = estimator.deploy(1, cpu_instance_type, endpoint_name=endpoint_name)
9999
_predict_and_assert(predictor)
100100

101101

tests/integ/test_factorization_machines.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from tests.integ.timeout import timeout, timeout_and_delete_endpoint_by_name
2525

2626

27-
def test_factorization_machines(sagemaker_session):
27+
def test_factorization_machines(sagemaker_session, cpu_instance_type):
2828
job_name = unique_name_from_base("fm")
2929

3030
with timeout(minutes=TRAINING_DEFAULT_TIMEOUT_MINUTES):
@@ -38,7 +38,7 @@ def test_factorization_machines(sagemaker_session):
3838
fm = FactorizationMachines(
3939
role="SageMakerRole",
4040
train_instance_count=1,
41-
train_instance_type="ml.c4.xlarge",
41+
train_instance_type=cpu_instance_type,
4242
num_factors=10,
4343
predictor_type="regressor",
4444
epochs=2,
@@ -58,15 +58,15 @@ def test_factorization_machines(sagemaker_session):
5858
model = FactorizationMachinesModel(
5959
fm.model_data, role="SageMakerRole", sagemaker_session=sagemaker_session
6060
)
61-
predictor = model.deploy(1, "ml.c4.xlarge", endpoint_name=job_name)
61+
predictor = model.deploy(1, cpu_instance_type, endpoint_name=job_name)
6262
result = predictor.predict(train_set[0][:10])
6363

6464
assert len(result) == 10
6565
for record in result:
6666
assert record.label["score"] is not None
6767

6868

69-
def test_async_factorization_machines(sagemaker_session):
69+
def test_async_factorization_machines(sagemaker_session, cpu_instance_type):
7070
job_name = unique_name_from_base("fm")
7171

7272
with timeout(minutes=5):
@@ -80,7 +80,7 @@ def test_async_factorization_machines(sagemaker_session):
8080
fm = FactorizationMachines(
8181
role="SageMakerRole",
8282
train_instance_count=1,
83-
train_instance_type="ml.c4.xlarge",
83+
train_instance_type=cpu_instance_type,
8484
num_factors=10,
8585
predictor_type="regressor",
8686
epochs=2,
@@ -108,7 +108,7 @@ def test_async_factorization_machines(sagemaker_session):
108108
model = FactorizationMachinesModel(
109109
estimator.model_data, role="SageMakerRole", sagemaker_session=sagemaker_session
110110
)
111-
predictor = model.deploy(1, "ml.c4.xlarge", endpoint_name=job_name)
111+
predictor = model.deploy(1, cpu_instance_type, endpoint_name=job_name)
112112
result = predictor.predict(train_set[0][:10])
113113

114114
assert len(result) == 10

0 commit comments

Comments
 (0)