Skip to content
Snippets Groups Projects
Commit bc4614fb authored by Yifan Zhao's avatar Yifan Zhao
Browse files

Merge branch 'main' into temp

parents 5b4a3adf 81adf07f
No related branches found
No related tags found
No related merge requests found
...@@ -10,9 +10,9 @@ from torch.utils.data.dataloader import DataLoader ...@@ -10,9 +10,9 @@ from torch.utils.data.dataloader import DataLoader
from ._logging import PathLike from ._logging import PathLike
from .approxapp import ApproxKnob, KnobsT from .approxapp import ApproxKnob, KnobsT
from .modeledapp import ( from .modeledapp import (
IPerfModel, ICostModel,
IQoSModel, IQoSModel,
LinearPerfModel, LinearCostModel,
ModeledApp, ModeledApp,
QoSModelP1, QoSModelP1,
QoSModelP2, QoSModelP2,
...@@ -34,15 +34,27 @@ class TorchApproxKnob(ApproxKnob): ...@@ -34,15 +34,27 @@ class TorchApproxKnob(ApproxKnob):
@property @property
@abc.abstractmethod @abc.abstractmethod
def expected_speedup(self) -> float: def expected_speedup(self) -> float:
"""The speedup this knob is expected to provide. Used for cost prediction."""
pass pass
@abc.abstractmethod @abc.abstractmethod
def is_applicable(self, op: Module) -> bool: def is_applicable(self, op: Module) -> bool:
"""Returns True if this knob can be applied to this Module.
:param op: the module to check availability for.
:type op: torch.nn.Module
:rtype: torch.nn.Module
"""
pass pass
@abc.abstractmethod @abc.abstractmethod
def apply(self, op: Module) -> Module: def apply(self, op: Module) -> Module:
"""Applies knob to `module` and returns an approximated `module`.""" """Applies knob to a Module and returns an approximated Module.
:param op: the module to apply approximation on.
:type op: torch.nn.Module
:rtype: torch.nn.Module
"""
pass pass
...@@ -53,40 +65,35 @@ class TorchApp(ModeledApp, abc.ABC): ...@@ -53,40 +65,35 @@ class TorchApp(ModeledApp, abc.ABC):
r"""Adaptor for approximable PyTorch Modules with tensor output. r"""Adaptor for approximable PyTorch Modules with tensor output.
A TorchApp stores the PyTorch Module, datasets for tuning and calibration, A TorchApp stores the PyTorch Module, datasets for tuning and calibration,
set of available TorchApproxKnob each of which may be applied to some layer in the Module, set of available `TorchApproxKnob` each of which may be applied to some layer in the Module,
and the quality of service (QoS) metric of application (e.g., accuracy). and the quality of service (QoS) metric of application (e.g., accuracy).
It provides empirical tuning and predictive tuning capability (see `TorchApp.tune()`), It provides empirical tuning and predictive tuning capability,
automatically supporting `.modeledapp.LinearCostModel`,
Parameters `.modeledapp.QoSModelP1`, and `.modeledapp.QoSModelP2`.
----------
app_name: In contrast to `.approxapp.ApproxApp` and `.modeledapp.ModeledApp`,
Name of the application, which is used as an identifier in tuning sessions, etc. there should be no need to inherit from `TorchApp` in most use cases.
module:
The PyTorch module to tune. :param app_name: Name of the application, which is used as an identifier in tuning sessions, etc.
tune_dataloader: :param module: The PyTorch module to tune.
A dataset to use as inputs to module during tuning. (PyTorch DataLoader is conceptually :param tune_dataloader: A `torch.utils.data.Dataset` dataset to use as inputs to module during tuning.
an enumerable, batched dataset.) :param test_dataloader: A `torch.utils.data.Dataset` dataset used for QoS testing
test_dataloader: (see `test_configs` parameter of `ApproxModeledTuner.tune`).
A input dataset used for QoS testing (see `test_config` parameter of `ApproxModeledTuner.tune`). :param knobs: A set of `TorchApproxKnob` to be considered. Each knob has an `is_applicable()` method
knobs: which is used to determine which layer it can apply to.
A set of knobs to be considered. Each knob has an `is_applicable()` method `.approxes.get_knobs_from_file` returns a set of builtin knobs that will exactly fit here.
which is used to determine which layer it can apply to. :param tensor_to_qos: QoS metric function which computes QoS from the module's output.
tensor_to_qos: `.torchutil.accuracy` computes the classification accuracy which can be applied here.
QoS metric function which computes QoS from the module's output. :param combine_qos: A function to combine each batch's QoS into one value.
combine_qos: When QoS is Classification Accuracy, this will most likely be `numpy.mean`
A function to combine each batch's QoS into one value. (which is the default value).
When QoS is accuracy this will most likely be `mean()` (which is the default). :param target_device: The target device that this application should be tuned on.
device: :param torch_device: The PyTorch device where the model inference is run on.
The device to store module and perform inference on. By default is "cuda" This device should be able to run the implementations of the knobs
if CUDA is available, otherwise "cpu". available for this app on `target_device`.
model_storage_folder: :param model_storage_folder: A folder to store the serialized QoS models into.
A folder to store the serialized QoS models into. `QoSModelP1` will be serialized into ``model_storage_folder / "p1.pkl"``,
`QoSModelP1` will be serialized into `model_storage_folder / "p1.pkl"`, and `QoSModelP2` into ``model_storage_folder / "p2.json"``.
and `QoSModelP2` into `model_storage_folder / "p2.json"`.
See `QoSModelP1` and `QoSModelP2` for details.
Attributes
----------
""" """
def __init__( def __init__(
...@@ -98,7 +105,7 @@ class TorchApp(ModeledApp, abc.ABC): ...@@ -98,7 +105,7 @@ class TorchApp(ModeledApp, abc.ABC):
knobs: Set[TorchApproxKnob], knobs: Set[TorchApproxKnob],
tensor_to_qos: Callable[[torch.Tensor, Any], float], tensor_to_qos: Callable[[torch.Tensor, Any], float],
combine_qos: Callable[[np.ndarray], float] = np.mean, combine_qos: Callable[[np.ndarray], float] = np.mean,
tuning_device: str = None, target_device: str = None,
torch_device: Union[torch.device, str] = _default_device, torch_device: Union[torch.device, str] = _default_device,
model_storage_folder: Optional[PathLike] = None, model_storage_folder: Optional[PathLike] = None,
) -> None: ) -> None:
...@@ -107,7 +114,7 @@ class TorchApp(ModeledApp, abc.ABC): ...@@ -107,7 +114,7 @@ class TorchApp(ModeledApp, abc.ABC):
self.tune_loader = tune_dataloader self.tune_loader = tune_dataloader
self.test_loader = test_dataloader self.test_loader = test_dataloader
self.name_to_knob = { self.name_to_knob = {
k.name: k for k in self._check_and_filter_knob(knobs, tuning_device) k.name: k for k in self._check_and_filter_knob(knobs, target_device)
} }
self.tensor_to_qos = tensor_to_qos self.tensor_to_qos = tensor_to_qos
self.combine_qos = combine_qos self.combine_qos = combine_qos
...@@ -132,17 +139,17 @@ class TorchApp(ModeledApp, abc.ABC): ...@@ -132,17 +139,17 @@ class TorchApp(ModeledApp, abc.ABC):
self._op_costs[op_name] = summary.loc[op_name, "flops"] self._op_costs[op_name] = summary.loc[op_name, "flops"]
# Init parent class last # Init parent class last
super().__init__(op_knobs, tuning_device) super().__init__(op_knobs, target_device)
@property @property
def name(self) -> str: def name(self) -> str:
"""Returns the name of application.""" """Returns the name of application."""
return self.app_name return self.app_name
def get_models(self) -> List[Union[IPerfModel, IQoSModel]]: def get_models(self) -> List[Union[ICostModel, IQoSModel]]:
"""Returns a list of predictive tuning models. """Returns a list of predictive tuning models.
TorchApp in particular derives 1 performance model (LinearPerfModel) TorchApp in particular derives 1 performance model (LinearCostModel)
and 2 QoS models (QoSModelP1, QoSModelP2) automatically. and 2 QoS models (QoSModelP1, QoSModelP2) automatically.
""" """
...@@ -162,7 +169,7 @@ class TorchApp(ModeledApp, abc.ABC): ...@@ -162,7 +169,7 @@ class TorchApp(ModeledApp, abc.ABC):
p1_storage = self.model_storage / "p1.pkl" if self.model_storage else None p1_storage = self.model_storage / "p1.pkl" if self.model_storage else None
p2_storage = self.model_storage / "p2.json" if self.model_storage else None p2_storage = self.model_storage / "p2.json" if self.model_storage else None
return [ return [
LinearPerfModel(self, self._op_costs, self._knob_speedups), LinearCostModel(self, self._op_costs, self._knob_speedups),
QoSModelP1( QoSModelP1(
self, self._get_raw_output_valset, batched_valset_qos, p1_storage self, self._get_raw_output_valset, batched_valset_qos, p1_storage
), ),
......
...@@ -2,6 +2,12 @@ from torch import Tensor ...@@ -2,6 +2,12 @@ from torch import Tensor
def accuracy(output: Tensor, target: Tensor) -> float: def accuracy(output: Tensor, target: Tensor) -> float:
"""The "classification accuracy" metric (return value is between 0 and 100).
:param output: Probability distribution output from the model.
:param target: A 1d-tensor of labels, one for each input image, from the dataset.
"""
_, pred_labels = output.max(1) _, pred_labels = output.max(1)
n_correct = (pred_labels == target).sum().item() n_correct = (pred_labels == target).sum().item()
return n_correct / len(output) * 100 return n_correct / len(output) * 100
import setuptools import setuptools
with open("README.md", "r", encoding="utf-8") as fh: with open("README.rst", "r", encoding="utf-8") as fh:
long_description = fh.read() long_description = fh.read()
setuptools.setup( setuptools.setup(
...@@ -10,14 +10,18 @@ setuptools.setup( ...@@ -10,14 +10,18 @@ setuptools.setup(
author_email="yifanz16@illinois.edu", author_email="yifanz16@illinois.edu",
description="A package for predictive and empirical approximation autotuning", description="A package for predictive and empirical approximation autotuning",
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/x-rst",
url="https://github.com/Evan-Zhao/predictive-tuner", url="https://github.com/Evan-Zhao/predictive-tuner",
packages=["predtuner"], packages=setuptools.find_packages(),
package_data={
"predtuner.approxes": ["default_approx_params.json"]
},
include_package_data=True,
install_requires=[ install_requires=[
"matplotlib>=3.3", "matplotlib>=3.3",
"networkx>=2.5", "networkx>=2.5",
"torch==1.7.1", "torch>=1.5.1",
"torchvision==0.8.2", "torchvision>=0.6",
"tqdm>=4.50", "tqdm>=4.50",
"pandas>=1.1", "pandas>=1.1",
"jsonpickle>=1.5", "jsonpickle>=1.5",
......
...@@ -41,7 +41,7 @@ class TestTorchAppTuning(TorchAppSetUp): ...@@ -41,7 +41,7 @@ class TestTorchAppTuning(TorchAppSetUp):
self.assertEqual(self.app.baseline_knob.name, "11") self.assertEqual(self.app.baseline_knob.name, "11")
def test_cpu_knobs(self): def test_cpu_knobs(self):
app = TorchApp(**self.app_args, tuning_device="cpu") app = TorchApp(**self.app_args, target_device="cpu")
n_knobs = {op: len(ks) for op, ks in app.op_knobs.items()} n_knobs = {op: len(ks) for op, ks in app.op_knobs.items()}
for op_name, op in app.midx.name_to_module.items(): for op_name, op in app.midx.name_to_module.items():
nknob = 28 if isinstance(op, Conv2d) else 1 nknob = 28 if isinstance(op, Conv2d) else 1
...@@ -49,7 +49,7 @@ class TestTorchAppTuning(TorchAppSetUp): ...@@ -49,7 +49,7 @@ class TestTorchAppTuning(TorchAppSetUp):
self.assertEqual(app.baseline_knob.name, "11") self.assertEqual(app.baseline_knob.name, "11")
def test_gpu_knobs(self): def test_gpu_knobs(self):
app = TorchApp(**self.app_args, tuning_device="gpu") app = TorchApp(**self.app_args, target_device="gpu")
n_knobs = {op: len(ks) for op, ks in app.op_knobs.items()} n_knobs = {op: len(ks) for op, ks in app.op_knobs.items()}
for op_name, op in app.midx.name_to_module.items(): for op_name, op in app.midx.name_to_module.items():
nknob = 28 if isinstance(op, Conv2d) else 1 nknob = 28 if isinstance(op, Conv2d) else 1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment