docker_base.py 6.37 KB
Newer Older
1
2
3
4
5
6
7
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.

"""Module of the docker-benchmark base class."""

from abc import abstractmethod

8
9
from superbench.common.utils import logger, run_command
from superbench.benchmarks import BenchmarkType, ReturnCode
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from superbench.benchmarks.base import Benchmark


class DockerBenchmark(Benchmark):
    """The base class of benchmarks packaged in docker container."""
    def __init__(self, name, parameters=''):
        """Constructor.

        Args:
            name (str): benchmark name.
            parameters (str): benchmark parameters.
        """
        super().__init__(name, parameters)
        self._benchmark_type = BenchmarkType.DOCKER
24

25
        # Command lines to launch the docker image and run the benchmarks inside docker.
26
27
28
29
30
31
32
        self._commands = list()

        # Image uri of the current docker-benchmark.
        self._image_uri = None

        # Container name of the current docker-benchmark.
        self._container_name = None
33

34
35
36
37
38
39
40
41
42
43
44
45
        # Default options for docker run.
        self._default_options = '-i --rm --privileged --net=host --ipc=host'

        # Platform-specific options for docker run.
        self._platform_options = None

        # Entrypoint option of the current docker-benchmark.
        self._entrypoint = None

        # CMD option of the current docker-benchmark.
        self._cmd = None

46
47
48
49
50
51
52
53
54
55
56
57
58
    '''
    # If need to add new arguments, super().add_parser_arguments() must be called.
    def add_parser_arguments(self):
        """Add the specified arguments."""
        super().add_parser_arguments()
    '''

    def _preprocess(self):
        """Preprocess/preparation operations before the benchmarking.

        Return:
            True if _preprocess() succeed.
        """
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
        if not super()._preprocess():
            return False

        if self._image_uri is None:
            self._result.set_return_code(ReturnCode.DOCKERBENCHMARK_IMAGE_NOT_SET)
            logger.error('The image uri is not set - benchmark: {}.'.format(self._name))
            return False

        if self._container_name is None:
            self._result.set_return_code(ReturnCode.DOCKERBENCHMARK_CONTAINER_NOT_SET)
            logger.error('The container name is not set - benchmark: {}.'.format(self._name))
            return False

        output = run_command('docker pull --quiet {}'.format(self._image_uri))
        if output.returncode != 0:
            self._result.set_return_code(ReturnCode.DOCKERBENCHMARK_IMAGE_PULL_FAILURE)
            logger.error(
                'DockerBenchmark pull image failed - benchmark: {}, error message: {}.'.format(
                    self._name, output.stdout
                )
            )
            return False

82
83
84
85
86
87
88
89
90
91
92
93
94
        command = 'docker run '
        command += self._default_options
        command += ' --name={container_name} {platform_options} {entrypoint} {image} {cmd}'
        self._commands.append(
            command.format(
                container_name=self._container_name,
                platform_options=self._platform_options or '',
                entrypoint='' if self._entrypoint is None else '--entrypoint {}'.format(self._entrypoint),
                image=self._image_uri,
                cmd=self._cmd or ''
            )
        )

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
        return True

    def _postprocess(self):
        """Postprocess/cleanup operations after the benchmarking.

        Return:
            True if _postprocess() succeed.
        """
        rm_containers = 'docker stop --time 20 {container} && docker rm {container}'.format(
            container=self._container_name
        )
        run_command(rm_containers)

        rm_image = 'docker rmi {}'.format(self._image_uri)
        run_command(rm_image)

        return True
112
113

    def _benchmark(self):
114
        """Implementation for benchmarking.
115

116
117
118
119
120
121
122
123
124
        Return:
            True if run benchmark successfully.
        """
        for cmd_idx in range(len(self._commands)):
            logger.info(
                'Execute command - round: {}, benchmark: {}, command: {}.'.format(
                    self._curr_run_index, self._name, self._commands[cmd_idx]
                )
            )
125
            output = run_command(self._commands[cmd_idx], flush_output=self._args.log_flushing)
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
            if output.returncode != 0:
                self._result.set_return_code(ReturnCode.DOCKERBENCHMARK_EXECUTION_FAILURE)
                logger.error(
                    'DockerBenchmark execution failed - round: {}, benchmark: {}, error message: {}.'.format(
                        self._curr_run_index, self._name, output.stdout
                    )
                )
                return False
            else:
                if not self._process_raw_result(cmd_idx, output.stdout):
                    self._result.set_return_code(ReturnCode.DOCKERBENCHMARK_RESULT_PARSING_FAILURE)
                    return False

        return True

    @abstractmethod
    def _process_raw_result(self, cmd_idx, raw_output):
143
144
        """Function to process raw results and save the summarized results.

145
146
          self._result.add_raw_data() and self._result.add_result() need to be called to save the results.

147
        Args:
148
149
            cmd_idx (int): the index of command corresponding with the raw_output.
            raw_output (str): raw output string of the docker-benchmark.
150
151
152

        Return:
            True if the raw output string is valid and result can be extracted.
153
        """
154
        pass
155
156
157
158
159

    def print_env_info(self):
        """Print environments or dependencies information."""
        # TODO: will implement it when add real benchmarks in the future.
        pass
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185


class CudaDockerBenchmark(DockerBenchmark):
    """The base class of benchmarks packaged in nvidia docker container."""
    def __init__(self, name, parameters=''):
        """Constructor.

        Args:
            name (str): benchmark name.
            parameters (str): benchmark parameters.
        """
        super().__init__(name, parameters)
        self._platform_options = '--gpus=all'


class RocmDockerBenchmark(DockerBenchmark):
    """The base class of benchmarks packaged in amd docker container."""
    def __init__(self, name, parameters=''):
        """Constructor.

        Args:
            name (str): benchmark name.
            parameters (str): benchmark parameters.
        """
        super().__init__(name, parameters)
        self._platform_options = '--security-opt seccomp=unconfined --group-add video'