resources,stdlib: Add workload to resource specialization and deprecate workload.py (#212)
This commit is contained in:
@@ -28,7 +28,7 @@ from abc import ABCMeta, abstractmethod
|
||||
import inspect
|
||||
|
||||
from .mem_mode import MemMode, mem_mode_to_string
|
||||
from ...resources.workload import AbstractWorkload
|
||||
from ...resources.resource import WorkloadResource
|
||||
|
||||
from m5.objects import (
|
||||
AddrRange,
|
||||
@@ -198,7 +198,7 @@ class AbstractBoard:
|
||||
)
|
||||
return self._is_fs
|
||||
|
||||
def set_workload(self, workload: AbstractWorkload) -> None:
|
||||
def set_workload(self, workload: WorkloadResource) -> None:
|
||||
"""
|
||||
Set the workload for this board to run.
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ from .downloader import get_resource
|
||||
from .looppoint import LooppointCsvLoader, LooppointJsonLoader
|
||||
from ..isas import ISA, get_isa_from_str
|
||||
|
||||
from typing import Optional, Dict, Union, Type, Tuple, List
|
||||
from typing import Optional, Dict, Union, Type, Tuple, List, Any
|
||||
|
||||
from .client import get_resource_json_obj
|
||||
|
||||
@@ -554,6 +554,66 @@ class SimpointDirectoryResource(SimpointResource):
|
||||
return simpoint_list, weight_list
|
||||
|
||||
|
||||
class WorkloadResource(AbstractResource):
|
||||
"""A workload resource. This resource is used to specify a workload to run
|
||||
on a board. It contains the function to call and the parameters to pass to
|
||||
that function.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
function: str = None,
|
||||
resource_version: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
source: Optional[str] = None,
|
||||
local_path: Optional[str] = None,
|
||||
parameters: Optional[Dict[str, Any]] = {},
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
:param function: The function to call on the board.
|
||||
:param parameters: The parameters to pass to the function.
|
||||
"""
|
||||
|
||||
super().__init__(
|
||||
local_path=local_path,
|
||||
description=description,
|
||||
source=source,
|
||||
resource_version=resource_version,
|
||||
)
|
||||
|
||||
self._func = function
|
||||
self._params = parameters
|
||||
|
||||
def get_function_str(self) -> str:
|
||||
"""
|
||||
Returns the name of the workload function to be run.
|
||||
|
||||
This function is called via the AbstractBoard's `set_workload`
|
||||
function. The parameters from the `get_parameters` function are passed
|
||||
to this function.
|
||||
"""
|
||||
return self._func
|
||||
|
||||
def get_parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a dictionary mapping the workload parameters to their values.
|
||||
|
||||
These parameters are passed to the function specified by
|
||||
`get_function_str` via the AbstractBoard's `set_workload` function.
|
||||
"""
|
||||
return self._params
|
||||
|
||||
def set_parameter(self, parameter: str, value: Any) -> None:
|
||||
"""
|
||||
Used to set or override a workload parameter
|
||||
|
||||
:param parameter: The parameter of the function to set.
|
||||
:param value: The value to set to the parameter.
|
||||
"""
|
||||
self._params[parameter] = value
|
||||
|
||||
|
||||
def obtain_resource(
|
||||
resource_id: str,
|
||||
resource_directory: Optional[str] = None,
|
||||
@@ -658,6 +718,26 @@ def obtain_resource(
|
||||
assert resources_category in _get_resource_json_type_map
|
||||
resource_class = _get_resource_json_type_map[resources_category]
|
||||
|
||||
if resources_category == "workload":
|
||||
# This parses the "resources" and "additional_params" fields of the
|
||||
# workload resource into a dictionary of AbstractResource objects and
|
||||
# strings respectively.
|
||||
params = {}
|
||||
if "resources" in resource_json:
|
||||
for key in resource_json["resources"].keys():
|
||||
assert isinstance(key, str)
|
||||
value = resource_json["resources"][key]
|
||||
assert isinstance(value, str)
|
||||
params[key] = obtain_resource(
|
||||
value,
|
||||
)
|
||||
if "additional_params" in resource_json:
|
||||
for key in resource_json["additional_params"].keys():
|
||||
assert isinstance(key, str)
|
||||
value = resource_json["additional_params"][key]
|
||||
assert isinstance(value, str)
|
||||
params[key] = value
|
||||
resource_json["parameters"] = params
|
||||
# Once we know what AbstractResource subclass we are using, we create it.
|
||||
# The fields in the JSON object are assumed to map like-for-like to the
|
||||
# subclass contructor, so we can pass the resource_json map directly.
|
||||
@@ -812,4 +892,5 @@ _get_resource_json_type_map = {
|
||||
"resource": Resource,
|
||||
"looppoint-pinpoint-csv": LooppointCsvResource,
|
||||
"looppoint-json": LooppointJsonResource,
|
||||
"workload": WorkloadResource,
|
||||
}
|
||||
|
||||
@@ -24,219 +24,67 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from .resource import obtain_resource
|
||||
from .resource import obtain_resource, WorkloadResource
|
||||
from .client import get_resource_json_obj
|
||||
|
||||
from _m5 import core
|
||||
from m5.util import warn
|
||||
|
||||
from typing import Dict, Any, List, Optional
|
||||
|
||||
|
||||
class AbstractWorkload:
|
||||
def CustomWorkload(function: str, parameters: Dict[str, Any]):
|
||||
"""
|
||||
Workloads contain information needed to build a workload.
|
||||
A custom workload gem5 resource. It can be used to specify a custom,
|
||||
local workload.
|
||||
|
||||
A workload specifies a function and its parameters to run on a board to
|
||||
set a workload. Workload's are passed to board via the `AbstractBoard`'s
|
||||
`set_workload` function.
|
||||
**Warning**: This `CustomWorkload` class is deprecated. It will be removed in a
|
||||
future release of gem5. Please use the `gem5.resources.resource.WorkloadResource`
|
||||
class instead.
|
||||
|
||||
The `AbstractBoard` has a `set_workload` function which accepts an
|
||||
AbstractWorkload. The `set_workload` function uses the `get_function_str`
|
||||
to determine which function should be called on the board and the
|
||||
`get_parameters` function specifies the parameters to be passed.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
```py
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : obtain_resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
The class has been stealthily converted to a function which wraps the
|
||||
`WorkloadResource` class.
|
||||
"""
|
||||
warn(
|
||||
"The `CustomWorkload` class is deprecated. Please use "
|
||||
"the `gem5.resources.resource.WorkloadResource` class instead."
|
||||
)
|
||||
return WorkloadResource(function=function, parameters=parameters)
|
||||
|
||||
board.set_workload(workload)
|
||||
```
|
||||
|
||||
The above is the equivalent of:
|
||||
def Workload(
|
||||
workload_name: str,
|
||||
resource_directory: Optional[str] = None,
|
||||
resource_version: Optional[str] = None,
|
||||
clients: Optional[List] = None,
|
||||
gem5_version: Optional[str] = core.gem5Version,
|
||||
):
|
||||
"""
|
||||
**Warning**: The `Workload` class is deprecated. It will be removed in a
|
||||
future release of gem5. Please use the `gem5.resources.resource.WorkloadResource`
|
||||
class instead.
|
||||
|
||||
```py
|
||||
board.set_se_binary_workload(
|
||||
binary = obtain_resource("x86-print-this"),
|
||||
arguments = ["hello", 6],
|
||||
The class has been stealthily converted to a function which wraps the
|
||||
`WorkloadResource` class.
|
||||
"""
|
||||
warn(
|
||||
"`Workload` has been deprecated. Please use the `obtain_resource` "
|
||||
"function instead:\n\n"
|
||||
"```\n"
|
||||
"from gem5.resources.resource import obtain_resource\n"
|
||||
"workload = obtain_resource(\n"
|
||||
f' resource_id="{workload_name}",\n'
|
||||
f' resource_directory="{resource_directory}",\n'
|
||||
f' gem5_version="{gem5_version}",\n'
|
||||
f" clients={clients},\n"
|
||||
f" resource_version={resource_version},\n"
|
||||
")\n"
|
||||
"```"
|
||||
)
|
||||
```
|
||||
|
||||
Notes
|
||||
-----
|
||||
This class should not be used directly. Please use `Workload` or
|
||||
`CustomWorkload`.
|
||||
"""
|
||||
|
||||
def __init__(self, function: str, parameters: Dict[str, Any]) -> None:
|
||||
self._func = function
|
||||
self._params = parameters
|
||||
|
||||
def get_function_str(self) -> str:
|
||||
"""
|
||||
Returns the name of the workload function to be run.
|
||||
|
||||
This function is called via the AbstractBoard's `set_workload`
|
||||
function. The parameters from the `get_parameters` function are passed
|
||||
to this function.
|
||||
"""
|
||||
return self._func
|
||||
|
||||
def get_parameters(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a dictionary mapping the workload parameters to their values.
|
||||
|
||||
These parameters are passed to the function specified by
|
||||
`get_function_str` via the AbstractBoard's `set_workload` function.
|
||||
"""
|
||||
return self._params
|
||||
|
||||
def set_parameter(self, parameter: str, value: Any) -> None:
|
||||
"""
|
||||
Used to set or override a workload parameter
|
||||
|
||||
:param parameter: The parameter of the function to set.
|
||||
:param value: The value to set to the parameter.
|
||||
"""
|
||||
self._params[parameter] = value
|
||||
|
||||
|
||||
class CustomWorkload(AbstractWorkload):
|
||||
"""
|
||||
A workload specified locally (i.e., not via gem5-resources as with the
|
||||
`Workload` class). Here the user specifies the function and the parameters
|
||||
to be passed.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```py
|
||||
workload = CustomWorkload(
|
||||
function = "set_se_binary_workload",
|
||||
parameters = {
|
||||
"binary" : obtain_resource("x86-print-this"),
|
||||
"arguments" : ["hello", 6]
|
||||
},
|
||||
return obtain_resource(
|
||||
workload_name,
|
||||
resource_directory=resource_directory,
|
||||
gem5_version=gem5_version,
|
||||
clients=clients,
|
||||
resource_version=resource_version,
|
||||
)
|
||||
|
||||
board.set_workload(workload)
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(self, function: str, parameters: Dict[str, Any]) -> None:
|
||||
super().__init__(function=function, parameters=parameters)
|
||||
|
||||
|
||||
class Workload(AbstractWorkload):
|
||||
"""
|
||||
The `Workload` class loads a workload's information from gem5-resources
|
||||
based on a name/id passed via the constructor.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```py
|
||||
# Determine what workload we want to run.
|
||||
workload = Workload("example-workload-id")
|
||||
|
||||
# Optionally we can override a parameter in the workload. In this example
|
||||
# we are going to run this workload with a difference kernel.
|
||||
workload.set_parameter("kernel",
|
||||
obtain_resource("arm64-linux-kernel-4.14.134")
|
||||
)
|
||||
|
||||
# We then set this workload to the board.
|
||||
board.set_workload(workload)
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
workload_name: str,
|
||||
resource_directory: Optional[str] = None,
|
||||
resource_version: Optional[str] = None,
|
||||
clients: Optional[List] = None,
|
||||
gem5_version: Optional[str] = core.gem5Version,
|
||||
) -> None:
|
||||
"""
|
||||
This constructor will load the workload details from the workload with
|
||||
the given name/id.
|
||||
|
||||
This function assumes the dictionary returned by the downloader's
|
||||
`get_workload_json_obj` is a dictionary. An example of the schema is
|
||||
shown below:
|
||||
|
||||
```json
|
||||
{
|
||||
"category" : "workload",
|
||||
"id" : "x86-ubuntu-18.04-echo-hello",
|
||||
"description" : "Description of workload here",
|
||||
"function" : "set_kernel_disk_workload",
|
||||
"resources" : {
|
||||
"kernel" : "x86-linux-kernel-5.4.49",
|
||||
"disk-image" : "x86-ubuntu-18.04-img"
|
||||
},
|
||||
"additional_params" : {
|
||||
"readfile_contents" : "m5_exit; echo 'hello'; m5_exit"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This resource will result in the equivalent of the following action
|
||||
being taken:
|
||||
|
||||
```python
|
||||
board.set_kernel_disk_workload(
|
||||
kernel = obtain_resource("x86-linux-kernel-5.4.49"),
|
||||
disk-image = obtain_resource("x86-ubuntu-18.04-img"),
|
||||
readfile_contents = "m5_exit; echo 'hello'; m5_exit",
|
||||
)
|
||||
```
|
||||
|
||||
:param workload_name: The name of the workload in the resources.json
|
||||
file to be loaded.
|
||||
:param resource_directory: An optional parameter that specifies where
|
||||
any resources should be download and accessed from. If None, a default
|
||||
location will be used. None by default.
|
||||
:param gem5_version: The gem5 version for the Workload to be loaded.
|
||||
By default, the current gem5 version is used. This will filter
|
||||
resources which are incompatible with the current gem5 version. If
|
||||
None, no filtering will be done.
|
||||
"""
|
||||
|
||||
workload_json = get_resource_json_obj(
|
||||
workload_name,
|
||||
resource_version=resource_version,
|
||||
clients=clients,
|
||||
gem5_version=gem5_version,
|
||||
)
|
||||
|
||||
func = workload_json["function"]
|
||||
assert isinstance(func, str)
|
||||
|
||||
params = {}
|
||||
if "resources" in workload_json:
|
||||
for key in workload_json["resources"].keys():
|
||||
assert isinstance(key, str)
|
||||
value = workload_json["resources"][key]
|
||||
assert isinstance(value, str)
|
||||
params[key] = obtain_resource(
|
||||
value,
|
||||
resource_directory=resource_directory,
|
||||
gem5_version=gem5_version,
|
||||
)
|
||||
|
||||
if "additional_params" in workload_json:
|
||||
for key in workload_json["additional_params"]:
|
||||
assert isinstance(key, str)
|
||||
params[key] = workload_json["additional_params"][key]
|
||||
|
||||
super().__init__(function=func, parameters=params)
|
||||
|
||||
Reference in New Issue
Block a user