resources,stdlib: Add workload to resource specialization and deprecate workload.py (#212)

This commit is contained in:
Bobby R. Bruce
2023-09-07 12:45:45 -07:00
committed by GitHub
15 changed files with 158 additions and 227 deletions

View File

@@ -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.

View File

@@ -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,
}

View File

@@ -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)