Skip to content

Fixes for MLC docker run #136

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

Merged
merged 14 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 42 additions & 41 deletions automation/script/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def dockerfile(self_module, input_params):
is_console_output = input_params.get('out') == 'con'

# Step 2: Search for scripts
search_result = self_module.search(input_params)
search_result = self_module.search(input_params.copy())
if search_result['return'] > 0:
return search_result

Expand Down Expand Up @@ -133,32 +133,9 @@ def dockerfile(self_module, input_params):

run_command_string = regenerate_result['run_cmd_string']

# Collect Dockerfile inputs
dockerfile_inputs = {
key: input_params.get(
f"docker_{key}", docker_settings.get(
key, get_docker_default(key)))
for key in [
"mlc_repo", "mlc_repo_branch", "base_image", "os", "os_version",
"mlc_repos", "skip_mlc_sys_upgrade", "extra_sys_deps",
"gh_token", "fake_run_deps", "run_final_cmds", "real_run", "copy_files", "path"
]
if (value := input_params.get(f"docker_{key}", docker_settings.get(key, get_docker_default(key)))) is not None
}

# Determine Dockerfile suffix and path
docker_base_image = dockerfile_inputs.get('base_image')
docker_path = dockerfile_inputs.get('path')
if not docker_path:
docker_path = script_directory
docker_filename_suffix = (
docker_base_image.replace('/', '-').replace(':', '-')
if docker_base_image else f"{dockerfile_inputs['os']}_{dockerfile_inputs['os_version']}"
)
dockerfile_path = os.path.join(
docker_path,
'dockerfiles',
f"{docker_filename_suffix}.Dockerfile")
# Prepare Docker-specific inputs
docker_inputs, dockerfile_path = prepare_docker_inputs(
input_params, docker_settings, script_directory)

# Handle optional dependencies and comments
if input_params.get('print_deps'):
Expand All @@ -182,13 +159,13 @@ def dockerfile(self_module, input_params):
# Generate Dockerfile
mlc_docker_input = {
'action': 'run', 'automation': 'script', 'tags': 'build,dockerfile',
'fake_run_option': " " if dockerfile_inputs.get('real_run') else " --fake_run",
'fake_run_option': " " if docker_inputs.get('real_run') else " --fake_run",
'comments': comments, 'run_cmd': f"{run_command_string} --quiet",
'script_tags': input_params.get('tags'), 'env': environment_vars,
'dockerfile_env': dockerfile_environment_vars,
'quiet': True, 'v': input_params.get('v', False), 'real_run': True
}
mlc_docker_input.update(dockerfile_inputs)
mlc_docker_input.update(docker_inputs)

dockerfile_result = self_module.action_object.access(mlc_docker_input)
if dockerfile_result['return'] > 0:
Expand All @@ -215,33 +192,33 @@ def docker_run(self_module, i):

# Extract and handle basic inputs
quiet = i.get('quiet', False)
detached = i.get('docker_detached', i.get('docker_dt', 'no'))
interactive = i.get('docker_interactive', i.get('docker_it', ''))
verbose = i.get('v', False)
show_time = i.get('show_time', False)

env = i.get('env', {})
noregenerate_docker_file = i.get('docker_noregenerate', False)
norecreate_docker_image = not i.get('docker_recreate', False)

regenerate_docker_file = not i.get('docker_noregenerate', False)
recreate_docker_image = i.get('docker_recreate', False)

if i.get('docker_skip_build', False):
noregenerate_docker_file = True
norecreate_docker_image = True
regenerate_docker_file = False
recreate_docker_image = False
env['MLC_DOCKER_SKIP_BUILD'] = 'yes'

# Prune unnecessary Docker-related input keys
r = prune_input({'input': i, 'extra_keys_starts_with': ['docker_']})
f_run_cmd = r['new_input']

print(f"regenerate_docker_file = {regenerate_docker_file}")
# Regenerate Dockerfile if required
if not noregenerate_docker_file:
if regenerate_docker_file:
r = dockerfile(self_module, i)
if r['return'] > 0:
return r

# Save current directory and prepare to search for scripts
cur_dir = os.getcwd()
r = self_module.search(i)
r = self_module.search(i.copy())
if r['return'] > 0:
return r

Expand All @@ -253,7 +230,7 @@ def docker_run(self_module, i):
state, const, const_state = i.get(
'state', {}), i.get(
'const', {}), i.get(
'const_state', {})
'const_state', {})
variation_tags = [t[1:]
for t in i.get('tags', '').split(",") if t.startswith("_")]

Expand Down Expand Up @@ -310,6 +287,29 @@ def docker_run(self_module, i):
if r['return'] > 0:
return r

docker_settings = state['docker']

deps = docker_settings.get('deps', [])
if deps:
r = self_module._run_deps(
deps, [], env, {}, {}, {}, {}, '', [], '', False, '', verbose,
show_time, ' ', run_state)
if r['return'] > 0:
return r

# For updating meta from update_meta_if_env
r = self_module.update_state_from_meta(
meta, env, state, const, const_state, deps=[],
post_deps=[],
prehook_deps=[],
posthook_deps=[],
new_env_keys=[],
new_state_keys=[],
run_state=run_state,
i=i)
if r['return'] > 0:
return r

# Skip scripts marked as non-runnable
if not docker_settings.get('run', True) and not i.get(
'docker_run_override', False):
Expand All @@ -327,7 +327,8 @@ def docker_run(self_module, i):

# Prepare Docker-specific inputs
docker_inputs, dockerfile_path = prepare_docker_inputs(
i, docker_settings, script_path)
i, docker_settings, script_path, True)

if docker_inputs is None:
return {'return': 1, 'error': 'Error preparing Docker inputs'}

Expand All @@ -343,8 +344,8 @@ def docker_run(self_module, i):
# Execute the Docker container
mlc_docker_input = {
'action': 'run', 'automation': 'script', 'tags': 'run,docker,container',
'recreate': 'yes' if not norecreate_docker_image else 'no',
'env': env, 'interactive': interactive, 'mounts': mounts, 'detached': detached,
'recreate': recreate_docker_image,
'env': env, 'mounts': mounts,
'script_tags': i.get('tags'), 'run_cmd': final_run_cmd, 'v': verbose,
'quiet': True, 'real_run': True, 'add_deps_recursive': {'build-docker-image': {'dockerfile': dockerfile_path}},
**docker_inputs
Expand Down
79 changes: 56 additions & 23 deletions automation/script/docker_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ def process_mounts(mounts, env, i, docker_settings):
return None


def prepare_docker_inputs(i, docker_settings, script_path):
def prepare_docker_inputs(input_params, docker_settings,
script_path, run_stage=False):
"""
Prepares Docker-specific inputs such as Dockerfile path and runtime options.

Expand All @@ -49,23 +50,49 @@ def prepare_docker_inputs(i, docker_settings, script_path):
Returns:
Tuple with Docker inputs dictionary and Dockerfile path or None in case of an error.
"""
try:
dockerfile_path = os.path.join(
script_path, docker_settings.get(
'dockerfile', 'Dockerfile'))
docker_args = docker_settings.get('args', {})
docker_image = i.get('docker_image', docker_settings.get('image', ''))

docker_inputs = {
'dockerfile': dockerfile_path,
'docker_image': docker_image,
'docker_args': docker_args
}

return docker_inputs, dockerfile_path
except Exception as e:
logging.error(f"Error preparing Docker inputs: {e}")
return None, None

keys = [
"mlc_repo", "mlc_repo_branch", "base_image", "os", "os_version",
"mlc_repos", "skip_mlc_sys_upgrade", "extra_sys_deps",
"gh_token", "fake_run_deps", "run_final_cmds", "real_run", "copy_files", "path"
]

if run_stage:
keys += [
"skip_run_cmd", "pre_run_cmds", "run_cmd_prefix", "all_gpus", "num_gpus", "device", "gh_token",
"port_maps", "shm_size", "pass_user_id", "pass_user_group", "extra_run_args", "detached", "interactive",
"dt", "it"
]
# Collect Dockerfile inputs
docker_inputs = {
key: input_params.get(
f"docker_{key}", docker_settings.get(
key, get_docker_default(key)))
for key in keys
if (value := input_params.get(f"docker_{key}", docker_settings.get(key, get_docker_default(key)))) is not None
}

if docker_inputs.get('detached', docker_inputs.get('dt')):
docker_inputs['interactive'] = False
docker_inputs['detached'] = True

# Determine Dockerfile suffix and path
docker_base_image = docker_inputs.get('base_image')
docker_path = docker_inputs.get('path')
if not docker_path:
docker_path = script_path
docker_filename_suffix = (
docker_base_image.replace('/', '-').replace(':', '-')
if docker_base_image else f"{docker_inputs['os']}_{docker_inputs['os_version']}"
)
dockerfile_path = os.path.join(
docker_path,
'dockerfiles',
f"{docker_filename_suffix}.Dockerfile")

docker_inputs['file_path'] = dockerfile_path

return docker_inputs, dockerfile_path


def update_docker_paths(path, mounts=None, force_target_path=''):
Expand Down Expand Up @@ -101,9 +128,9 @@ def update_docker_paths(path, mounts=None, force_target_path=''):
# Determine the mount string based on whether the path is a file or
# directory.
if os.path.isfile(host_path) or not os.path.isdir(host_path):
mount_entry = f"{os.path.dirname(host_path)}:{os.path.dirname(container_path)}"
mount_entry = f"""{os.path.dirname(host_path)}: {os.path.dirname(container_path)}"""
else:
mount_entry = f"{host_path}:{container_path}"
mount_entry = f"""{host_path}:{container_path}"""

# Add the mount entry to the mounts list if it's not already present.
if mounts is not None:
Expand Down Expand Up @@ -157,7 +184,7 @@ def regenerate_script_cmd(i):
docker_run_cmd_prefix = i.get('docker_run_cmd_prefix', '')

# Regenerate command from dictionary input
run_cmd = 'mlc run script'
run_cmd = 'mlcr'

skip_input_for_fake_run = docker_settings.get(
'skip_input_for_fake_run', [])
Expand Down Expand Up @@ -231,13 +258,19 @@ def rebuild_flags(
def get_docker_default(key):
defaults = {
"mlc_repo": "mlcommons@mlperf-automations",
"mlc_repo_branch": "mlc",
"mlc_repo_branch": "dev",
"os": "ubuntu",
"os_version": "24.04",
"fake_run_deps": False,
"run_final_cmds": [],
"skip_run_cmd": False,
"image_tag_extra": "-latest"
"image_tag_extra": "-latest",
"skip_run_cmd": False,
"pre_run_cmds": [],
"run_cmd_prefix": '',
"port_maps": [],
"detached": False,
"interactive": True
}
if key in defaults:
return defaults[key]
Expand Down
9 changes: 5 additions & 4 deletions script/app-mlperf-automotive/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,20 @@ deps:
- python
- python3

# Use cmind inside CM scripts
- tags: get,generic-python-lib,_package.cmind
# Use mlc inside scripts
#- tags: get,generic-python-lib,_package.mlcflow

- tags: get,mlperf,inference,utils


docker:
mlc_repo: gateoverflow@cm4mlops
mlc_repo: gateoverflow@mlperf-automations
mlc_repo_branch: dev
use_host_group_id: True
use_host_user_id: True
real_run: false
interactive: True
mlc_repos: 'cm pull repo mlcommons@cm4abtf --checkout=poc'
mlc_repos: 'mlc pull repo mlcommons@cm4abtf --branch=poc'
deps:
- tags: get,abtf,scratch,space
mounts:
Expand Down
4 changes: 2 additions & 2 deletions script/app-mlperf-inference/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1856,8 +1856,8 @@ docker:
MLC_MLPERF_INFERENCE_SUBMISSION_DIR: [ on ]

pre_run_cmds:
#- cm pull repo && mlcr --tags=get,git,repo,_repo.https://github.com/GATEOverflow/inference_results_v4.0.git --update
- cm pull repo
#- mlc pull repo && mlcr --tags=get,git,repo,_repo.https://github.com/GATEOverflow/inference_results_v4.0.git --update
- mlc pull repo
mounts:
- "${{ MLC_DATASET_IMAGENET_PATH }}:${{ MLC_DATASET_IMAGENET_PATH }}"
- "${{ MLC_DATASET_OPENIMAGES_PATH }}:${{ MLC_DATASET_OPENIMAGES_PATH }}"
Expand Down
6 changes: 3 additions & 3 deletions script/build-dockerfile/customize.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ def preprocess(i):
if env.get('MLC_DOCKER_RUN_SCRIPT_TAGS', '') != '':
script_tags = env['MLC_DOCKER_RUN_SCRIPT_TAGS']
found_scripts = automation.action_object.access(
{'action': 'search', 'automation': 'script', 'tags': script_tags})
{'action': 'search', 'target': 'script', 'tags': script_tags})
scripts_list = found_scripts['list']

if not scripts_list:
return {'return': 1,
'error': 'No CM script found for tags ' + script_tags}
'error': 'No automation script found for tags=' + script_tags}

if len(scripts_list) > 1:
return {
Expand Down Expand Up @@ -343,7 +343,7 @@ def preprocess(i):
if str(env.get('MLC_DOCKER_SKIP_MLC_SYS_UPGRADE', False)
).lower() not in ["true", "1", "yes"]:
f.write(EOL + '# Install all system dependencies' + EOL)
f.write('RUN mlc run script --tags=get,sys-utils-cm --quiet' + EOL)
f.write('RUN mlc run script --tags=get,sys-utils-mlc --quiet' + EOL)

if 'MLC_DOCKER_PRE_RUN_COMMANDS' in env:
for pre_run_cmd in env['MLC_DOCKER_PRE_RUN_COMMANDS']:
Expand Down
2 changes: 1 addition & 1 deletion script/build-dockerfile/dockerinfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"package-manager-update-cmd": "apt-get update -y",
"package-manager-get-cmd": "apt-get install -y",
"packages": [
"python3", "python3-pip", "git", "sudo", "wget", "python3-venv"
"python3", "python3-pip", "git", "sudo", "wget", "python3-venv", "systemctl"
],
"versions": {
"18.04": {
Expand Down
3 changes: 3 additions & 0 deletions script/build-dockerfile/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ input_mapping:
mlc_repo_branch: MLC_MLOPS_REPO_BRANCH
comments: MLC_DOCKER_RUN_COMMENTS
copy_files: MLC_DOCKER_COPY_FILES
base_image: MLC_DOCKER_IMAGE_BASE
os: MLC_DOCKER_OS
os_version: MLC_DOCKER_OS_VERSION
docker_base_image: MLC_DOCKER_IMAGE_BASE
docker_os: MLC_DOCKER_OS
docker_os_version: MLC_DOCKER_OS_VERSION
Expand Down
2 changes: 1 addition & 1 deletion script/build-mlperf-inference-server-nvidia/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ docker:
- yes

pre_run_cmds:
- cm pull repo
- mlc pull repo
run_cmd_prefix: sudo apt remove -y cmake
mounts:
- "${{ IMAGENET_PATH }}:/data/imagenet-val"
Expand Down
2 changes: 1 addition & 1 deletion script/generate-mlperf-inference-submission/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ docker:
os: ubuntu
os_version: '22.04'
pre_run_cmds:
- cm pull repo
- mlc pull repo
real_run: false
use_host_group_id: true
use_host_user_id: true
Expand Down
4 changes: 2 additions & 2 deletions script/get-platform-details/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ echo "------------------------------------------------------------" >> $OUTPUT_F

echo "11. Systemd service manager version" >> $OUTPUT_FILE
eval "systemctl --version | head -n 1" >> $OUTPUT_FILE
test $? -eq 0 || exit $?
#test $? -eq 0 || exit $?
echo "------------------------------------------------------------" >> $OUTPUT_FILE

echo "12. Services, from systemctl list-unit-files" >> $OUTPUT_FILE
eval "systemctl list-unit-files" >> $OUTPUT_FILE
test $? -eq 0 || exit $?
#test $? -eq 0 || exit $?
echo "------------------------------------------------------------" >> $OUTPUT_FILE

echo "13. Linux kernel boot-time arguments, from /proc/cmdline" >> $OUTPUT_FILE
Expand Down
Loading
Loading