-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor launcher user arg parsing (#4824)
Splitting work from #4769 because we are still debugging transformers integration issues. Parsing was broken for user arguments (see #4795). Additionally, parsing of user arguments is tricky and there are lots of edge cases. For example: #4660, #4716, #3967. I've attempted to accommodate all of the possible types of string inputs and added unit tests.
- Loading branch information
Showing
3 changed files
with
75 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
# DeepSpeed Team | ||
|
||
import pytest | ||
import subprocess | ||
|
||
from deepspeed.accelerator import get_accelerator | ||
|
||
if not get_accelerator().is_available(): | ||
pytest.skip("only supported in accelerator environments.", allow_module_level=True) | ||
|
||
user_arg_test_script = """import argparse | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument("--prompt", type=str) | ||
parser.add_argument("--local_rank", type=int, default=0) | ||
parser.add_argument("--world_size", type=int, default=1) | ||
args = parser.parse_args() | ||
print("ARG PARSE SUCCESS") | ||
""" | ||
|
||
|
||
@pytest.fixture(scope="function") | ||
def user_script_fp(tmpdir): | ||
script_fp = tmpdir.join("user_arg_test.py") | ||
with open(script_fp, "w") as f: | ||
f.write(user_arg_test_script) | ||
return script_fp | ||
|
||
|
||
@pytest.fixture(scope="function") | ||
def cmd(user_script_fp, prompt, multi_node): | ||
if multi_node: | ||
cmd = ("deepspeed", "--force_multi", "--num_nodes", "1", "--num_gpus", "1", user_script_fp, "--prompt", prompt) | ||
else: | ||
cmd = ("deepspeed", "--num_nodes", "1", "--num_gpus", "1", user_script_fp, "--prompt", prompt) | ||
return cmd | ||
|
||
|
||
@pytest.mark.parametrize("prompt", [ | ||
'''"I am 6' tall"''', """'I am 72" tall'""", """'"translate English to Romanian: "'""", | ||
'''I'm going to tell them "DeepSpeed is the best"''' | ||
]) | ||
@pytest.mark.parametrize("multi_node", [True, False]) | ||
def test_user_args(cmd): | ||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
out, err = p.communicate() | ||
assert "ARG PARSE SUCCESS" in out.decode("utf-8"), f"User args not parsed correctly: {err.decode('utf-8')}" | ||
|
||
|
||
def test_bash_string_args(tmpdir, user_script_fp): | ||
bash_script = f""" | ||
ARGS="--prompt 'DeepSpeed is the best'" | ||
echo ${{ARGS}}|xargs deepspeed --num_nodes 1 --num_gpus 1 {user_script_fp} | ||
""" | ||
|
||
bash_fp = tmpdir.join("bash_script.sh") | ||
with open(bash_fp, "w") as f: | ||
f.write(bash_script) | ||
|
||
p = subprocess.Popen(["bash", bash_fp], stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
out, err = p.communicate() | ||
assert "ARG PARSE SUCCESS" in out.decode("utf-8"), f"User args not parsed correctly: {err.decode('utf-8')}" |