From c9caea60ed00e506915c5d4ca19b8577a9a31182 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 10:36:24 -0400 Subject: [PATCH 01/11] fix transformers and quantization imports --- .../modifiers/obcq/utils/layer_compressor.py | 2 +- .../modifiers/quantization/utils/__init__.py | 13 +++++++++++++ .../sparsification}/obcq/utils/sparsegpt.py | 0 .../sparseml/modifiers/quantization/test_pytorch.py | 8 +++++++- 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 src/sparseml/modifiers/quantization/utils/__init__.py rename src/sparseml/{modifiers => transformers/sparsification}/obcq/utils/sparsegpt.py (100%) diff --git a/src/sparseml/modifiers/obcq/utils/layer_compressor.py b/src/sparseml/modifiers/obcq/utils/layer_compressor.py index 7a0197d07d2..d43ceb806da 100644 --- a/src/sparseml/modifiers/obcq/utils/layer_compressor.py +++ b/src/sparseml/modifiers/obcq/utils/layer_compressor.py @@ -20,8 +20,8 @@ import torch.nn as nn from torch.nn import Module -from sparseml.modifiers.obcq.utils.sparsegpt import SparseGPT from sparseml.pytorch.utils.helpers import get_dependency_order +from sparseml.transformers.sparsification.obcq.utils.sparsegpt import SparseGPT _LOGGER = logging.getLogger(__name__) diff --git a/src/sparseml/modifiers/quantization/utils/__init__.py b/src/sparseml/modifiers/quantization/utils/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/src/sparseml/modifiers/quantization/utils/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/sparseml/modifiers/obcq/utils/sparsegpt.py b/src/sparseml/transformers/sparsification/obcq/utils/sparsegpt.py similarity index 100% rename from src/sparseml/modifiers/obcq/utils/sparsegpt.py rename to src/sparseml/transformers/sparsification/obcq/utils/sparsegpt.py diff --git a/tests/sparseml/modifiers/quantization/test_pytorch.py b/tests/sparseml/modifiers/quantization/test_pytorch.py index b982c54cc44..27b0251aa80 100644 --- a/tests/sparseml/modifiers/quantization/test_pytorch.py +++ b/tests/sparseml/modifiers/quantization/test_pytorch.py @@ -26,6 +26,7 @@ from tests.sparseml.modifiers.conf import LifecyleTestingHarness, setup_modifier_factory from tests.sparseml.pytorch.helpers import ConvNet, LinearNet from tests.sparseml.pytorch.sparsification.quantization.test_modifier_quantization import ( # noqa E501 + _match_submodule_name_or_type, _test_qat_wrapped_module, _test_quantized_module, ) @@ -56,7 +57,12 @@ def _test_qat_applied(modifier, model): _test_qat_wrapped_module(model, name) elif is_quantizable: # check each target module is quantized - _test_quantized_module(model, modifier, module, name) + override_key = _match_submodule_name_or_type( + module, + name, + list(modifier.scheme_overrides.keys()), + ) + _test_quantized_module(model, modifier, module, name, override_key) else: # check all non-target modules are not quantized assert not hasattr(module, "quantization_scheme") From 71f1655b1b597077d8e45a83fae36358887722d2 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 10:57:00 -0400 Subject: [PATCH 02/11] update GHA --- .github/workflows/test-check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-check.yaml b/.github/workflows/test-check.yaml index 6ea07f3ac5e..8837b749cb8 100644 --- a/.github/workflows/test-check.yaml +++ b/.github/workflows/test-check.yaml @@ -148,7 +148,7 @@ jobs: - name: "⚙️ Install dependencies" run: pip3 install .[dev,torchvision,onnxruntime] - name: "🔬 Running pytorch tests" - run: make test TARGETS=pytorch + run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-pytorch-tests: runs-on: ubuntu-22.04 env: @@ -172,7 +172,7 @@ jobs: - name: "⚙️ Install dependencies" run: pip3 install .[dev,torchvision,onnxruntime] torch==1.9.1 - name: "🔬 Running pytorch tests" - run: make test TARGETS=pytorch + run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-onnx-tests: runs-on: ubuntu-22.04 env: From d682430f0ab3f38f19586b047f1e850addbb3105 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 11:06:22 -0400 Subject: [PATCH 03/11] transformers dependency --- .github/workflows/test-check.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-check.yaml b/.github/workflows/test-check.yaml index 8837b749cb8..75d5a60385e 100644 --- a/.github/workflows/test-check.yaml +++ b/.github/workflows/test-check.yaml @@ -146,7 +146,7 @@ jobs: - name: "Clean sparsezoo directory" run: rm -r sparsezoo/ - name: "⚙️ Install dependencies" - run: pip3 install .[dev,torchvision,onnxruntime] + run: pip3 install .[dev,torchvision,onnxruntime,transformers] - name: "🔬 Running pytorch tests" run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-pytorch-tests: @@ -170,7 +170,7 @@ jobs: - name: "Clean sparsezoo directory" run: rm -r sparsezoo/ - name: "⚙️ Install dependencies" - run: pip3 install .[dev,torchvision,onnxruntime] torch==1.9.1 + run: pip3 install .[dev,torchvision,onnxruntime,transformers] torch==1.9.1 - name: "🔬 Running pytorch tests" run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-onnx-tests: From ed4c67c976902c4bef9ad99dc40ecf5b25ec2044 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 11:12:57 -0400 Subject: [PATCH 04/11] move import --- .github/workflows/test-check.yaml | 4 ++-- src/sparseml/modifiers/obcq/utils/layer_compressor.py | 2 +- .../sparsification => modifiers}/obcq/utils/sparsegpt.py | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) rename src/sparseml/{transformers/sparsification => modifiers}/obcq/utils/sparsegpt.py (99%) diff --git a/.github/workflows/test-check.yaml b/.github/workflows/test-check.yaml index 75d5a60385e..8837b749cb8 100644 --- a/.github/workflows/test-check.yaml +++ b/.github/workflows/test-check.yaml @@ -146,7 +146,7 @@ jobs: - name: "Clean sparsezoo directory" run: rm -r sparsezoo/ - name: "⚙️ Install dependencies" - run: pip3 install .[dev,torchvision,onnxruntime,transformers] + run: pip3 install .[dev,torchvision,onnxruntime] - name: "🔬 Running pytorch tests" run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-pytorch-tests: @@ -170,7 +170,7 @@ jobs: - name: "Clean sparsezoo directory" run: rm -r sparsezoo/ - name: "⚙️ Install dependencies" - run: pip3 install .[dev,torchvision,onnxruntime,transformers] torch==1.9.1 + run: pip3 install .[dev,torchvision,onnxruntime] torch==1.9.1 - name: "🔬 Running pytorch tests" run: make test TARGETS=pytorch,modifiers compat-pytorch-1_9-onnx-tests: diff --git a/src/sparseml/modifiers/obcq/utils/layer_compressor.py b/src/sparseml/modifiers/obcq/utils/layer_compressor.py index d43ceb806da..7a0197d07d2 100644 --- a/src/sparseml/modifiers/obcq/utils/layer_compressor.py +++ b/src/sparseml/modifiers/obcq/utils/layer_compressor.py @@ -20,8 +20,8 @@ import torch.nn as nn from torch.nn import Module +from sparseml.modifiers.obcq.utils.sparsegpt import SparseGPT from sparseml.pytorch.utils.helpers import get_dependency_order -from sparseml.transformers.sparsification.obcq.utils.sparsegpt import SparseGPT _LOGGER = logging.getLogger(__name__) diff --git a/src/sparseml/transformers/sparsification/obcq/utils/sparsegpt.py b/src/sparseml/modifiers/obcq/utils/sparsegpt.py similarity index 99% rename from src/sparseml/transformers/sparsification/obcq/utils/sparsegpt.py rename to src/sparseml/modifiers/obcq/utils/sparsegpt.py index 179e833d1f2..cbdb77b40b8 100644 --- a/src/sparseml/transformers/sparsification/obcq/utils/sparsegpt.py +++ b/src/sparseml/modifiers/obcq/utils/sparsegpt.py @@ -18,7 +18,6 @@ import torch import torch.nn as nn -import transformers DEBUG = False @@ -42,6 +41,8 @@ class SparseGPT: """ def __init__(self, layer): + import transformers + self.layer = layer self.dev = self.layer.weight.device W = layer.weight.data.clone() @@ -61,6 +62,8 @@ def add_batch(self, inp: torch.Tensor, out: torch.Tensor): :param inp: tensor containing layer input :param out: tensor containing layer our """ + import transformers + if DEBUG: self._inp1 = inp self.out1 = out From 85466d652ef12b8f7bf802ec46729ec0ae27fae3 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 11:30:34 -0400 Subject: [PATCH 05/11] moving tests around --- .github/workflows/test-check.yaml | 4 ++-- Makefile | 2 +- src/sparseml/modifiers/obcq/utils/sparsegpt.py | 2 ++ tests/sparseml/modifiers/__init__.py | 13 +++++++++++++ tests/sparseml/modifiers/quantization/__init__.py | 13 +++++++++++++ tests/sparseml/pytorch/modifiers/__init__.py | 13 +++++++++++++ .../pytorch/modifiers/quantization/__init__.py | 13 +++++++++++++ .../modifiers/quantization/test_pytorch.py | 0 8 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/sparseml/modifiers/__init__.py create mode 100644 tests/sparseml/modifiers/quantization/__init__.py create mode 100644 tests/sparseml/pytorch/modifiers/__init__.py create mode 100644 tests/sparseml/pytorch/modifiers/quantization/__init__.py rename tests/sparseml/{ => pytorch}/modifiers/quantization/test_pytorch.py (100%) diff --git a/.github/workflows/test-check.yaml b/.github/workflows/test-check.yaml index 8837b749cb8..6ea07f3ac5e 100644 --- a/.github/workflows/test-check.yaml +++ b/.github/workflows/test-check.yaml @@ -148,7 +148,7 @@ jobs: - name: "⚙️ Install dependencies" run: pip3 install .[dev,torchvision,onnxruntime] - name: "🔬 Running pytorch tests" - run: make test TARGETS=pytorch,modifiers + run: make test TARGETS=pytorch compat-pytorch-1_9-pytorch-tests: runs-on: ubuntu-22.04 env: @@ -172,7 +172,7 @@ jobs: - name: "⚙️ Install dependencies" run: pip3 install .[dev,torchvision,onnxruntime] torch==1.9.1 - name: "🔬 Running pytorch tests" - run: make test TARGETS=pytorch,modifiers + run: make test TARGETS=pytorch compat-pytorch-1_9-onnx-tests: runs-on: ubuntu-22.04 env: diff --git a/Makefile b/Makefile index bcfcf77d686..c8600e281c9 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ ifneq ($(findstring onnx,$(TARGETS)),onnx) PYTEST_ARGS := $(PYTEST_ARGS) --ignore tests/sparseml/onnx endif ifneq ($(findstring pytorch,$(TARGETS)),pytorch) - PYTEST_ARGS := $(PYTEST_ARGS) --ignore tests/sparseml/pytorch --ignore tests/sparseml/modifiers + PYTEST_ARGS := $(PYTEST_ARGS) --ignore tests/sparseml/pytorch endif ifneq ($(findstring pytorch_models,$(TARGETS)),pytorch_models) PYTEST_ARGS := $(PYTEST_ARGS) --ignore tests/sparseml/pytorch/models diff --git a/src/sparseml/modifiers/obcq/utils/sparsegpt.py b/src/sparseml/modifiers/obcq/utils/sparsegpt.py index cbdb77b40b8..c1ee71ddd00 100644 --- a/src/sparseml/modifiers/obcq/utils/sparsegpt.py +++ b/src/sparseml/modifiers/obcq/utils/sparsegpt.py @@ -100,6 +100,8 @@ def fasterprune( :param percdamp: Amount of dampening to apply to H, as a fraction of the diagonal norm """ + import transformers + W = self.layer.weight.data.clone() if isinstance(self.layer, nn.Conv2d): W = W.flatten(1) diff --git a/tests/sparseml/modifiers/__init__.py b/tests/sparseml/modifiers/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/modifiers/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/modifiers/quantization/__init__.py b/tests/sparseml/modifiers/quantization/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/modifiers/quantization/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/pytorch/modifiers/__init__.py b/tests/sparseml/pytorch/modifiers/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/pytorch/modifiers/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/pytorch/modifiers/quantization/__init__.py b/tests/sparseml/pytorch/modifiers/quantization/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/pytorch/modifiers/quantization/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/modifiers/quantization/test_pytorch.py b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py similarity index 100% rename from tests/sparseml/modifiers/quantization/test_pytorch.py rename to tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py From 9149d62182e09b7d402f430f9b565e212196c09c Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 11:51:27 -0400 Subject: [PATCH 06/11] fix torch version issue --- src/sparseml/modifiers/obcq/__init__.py | 1 - src/sparseml/modifiers/quantization/__init__.py | 1 - .../pytorch/modifiers/quantization/test_pytorch.py | 10 ++++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sparseml/modifiers/obcq/__init__.py b/src/sparseml/modifiers/obcq/__init__.py index 22bafe8ce14..9cdf715c135 100644 --- a/src/sparseml/modifiers/obcq/__init__.py +++ b/src/sparseml/modifiers/obcq/__init__.py @@ -15,4 +15,3 @@ # flake8: noqa from .base import * -from .pytorch import * diff --git a/src/sparseml/modifiers/quantization/__init__.py b/src/sparseml/modifiers/quantization/__init__.py index 22bafe8ce14..9cdf715c135 100644 --- a/src/sparseml/modifiers/quantization/__init__.py +++ b/src/sparseml/modifiers/quantization/__init__.py @@ -15,4 +15,3 @@ # flake8: noqa from .base import * -from .pytorch import * diff --git a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py index 27b0251aa80..fe1ac58092a 100644 --- a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py +++ b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py @@ -13,12 +13,14 @@ # limitations under the License. import pytest +import torch +from packaging import version from sparseml.core import State from sparseml.core.event import Event, EventType from sparseml.core.factory import ModifierFactory from sparseml.core.framework import Framework -from sparseml.modifiers.quantization import QuantizationModifierPyTorch +from sparseml.modifiers.quantization.pytorch import QuantizationModifierPyTorch from sparseml.pytorch.sparsification.quantization.quantize import ( is_qat_helper_module, is_quantizable_module, @@ -90,9 +92,13 @@ def test_quantization_oneshot(model_class): state = State(framework=Framework.pytorch, start_event=Event()) state.update(model=model) + strategy = "channel" + TORCH_VERSION = version.parse(torch.__version__) + if TORCH_VERSION.major < 2: # per channel quant only supported in 2+ + strategy = "tensor" scheme = dict( input_activations=dict(num_bits=8, symmetric=True), - weights=dict(num_bits=4, symmetric=False, strategy="channel"), + weights=dict(num_bits=4, symmetric=False, strategy=strategy), ) kwargs = dict(scheme=scheme) From 6c0daf4a93b97ac0ce378261cc07af31446645f3 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 12:08:23 -0400 Subject: [PATCH 07/11] move all modifiers under pytorch --- tests/sparseml/modifiers/__init__.py | 13 ------------- tests/sparseml/modifiers/quantization/__init__.py | 13 ------------- tests/sparseml/{ => pytorch}/modifiers/conf.py | 0 .../modifiers/quantization/test_base.py | 2 +- .../pytorch/modifiers/quantization/test_pytorch.py | 2 +- 5 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 tests/sparseml/modifiers/__init__.py delete mode 100644 tests/sparseml/modifiers/quantization/__init__.py rename tests/sparseml/{ => pytorch}/modifiers/conf.py (100%) rename tests/sparseml/{ => pytorch}/modifiers/quantization/test_base.py (97%) diff --git a/tests/sparseml/modifiers/__init__.py b/tests/sparseml/modifiers/__init__.py deleted file mode 100644 index 0c44f887a47..00000000000 --- a/tests/sparseml/modifiers/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/tests/sparseml/modifiers/quantization/__init__.py b/tests/sparseml/modifiers/quantization/__init__.py deleted file mode 100644 index 0c44f887a47..00000000000 --- a/tests/sparseml/modifiers/quantization/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/tests/sparseml/modifiers/conf.py b/tests/sparseml/pytorch/modifiers/conf.py similarity index 100% rename from tests/sparseml/modifiers/conf.py rename to tests/sparseml/pytorch/modifiers/conf.py diff --git a/tests/sparseml/modifiers/quantization/test_base.py b/tests/sparseml/pytorch/modifiers/quantization/test_base.py similarity index 97% rename from tests/sparseml/modifiers/quantization/test_base.py rename to tests/sparseml/pytorch/modifiers/quantization/test_base.py index cd5fab0e755..5a238123590 100644 --- a/tests/sparseml/modifiers/quantization/test_base.py +++ b/tests/sparseml/pytorch/modifiers/quantization/test_base.py @@ -16,7 +16,7 @@ from sparseml.core.factory import ModifierFactory from sparseml.core.framework import Framework from sparseml.modifiers.quantization import QuantizationModifier -from tests.sparseml.modifiers.conf import setup_modifier_factory +from tests.sparseml.pytorch.modifiers.conf import setup_modifier_factory def test_quantization_registered(): diff --git a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py index fe1ac58092a..f5020155727 100644 --- a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py +++ b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py @@ -25,7 +25,7 @@ is_qat_helper_module, is_quantizable_module, ) -from tests.sparseml.modifiers.conf import LifecyleTestingHarness, setup_modifier_factory +from tests.sparseml.pytorch.modifiers.conf import LifecyleTestingHarness, setup_modifier_factory from tests.sparseml.pytorch.helpers import ConvNet, LinearNet from tests.sparseml.pytorch.sparsification.quantization.test_modifier_quantization import ( # noqa E501 _match_submodule_name_or_type, From 80115f3e10ce610887775b5c934b6e7b63de4550 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 12:27:52 -0400 Subject: [PATCH 08/11] fixing 1.9 tests --- .../pytorch/modifiers/quantization/test_pytorch.py | 13 +++++-------- .../quantization/test_modifier_quantization.py | 12 +++++++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py index f5020155727..b7e84699cea 100644 --- a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py +++ b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py @@ -13,8 +13,6 @@ # limitations under the License. import pytest -import torch -from packaging import version from sparseml.core import State from sparseml.core.event import Event, EventType @@ -25,8 +23,11 @@ is_qat_helper_module, is_quantizable_module, ) -from tests.sparseml.pytorch.modifiers.conf import LifecyleTestingHarness, setup_modifier_factory from tests.sparseml.pytorch.helpers import ConvNet, LinearNet +from tests.sparseml.pytorch.modifiers.conf import ( + LifecyleTestingHarness, + setup_modifier_factory, +) from tests.sparseml.pytorch.sparsification.quantization.test_modifier_quantization import ( # noqa E501 _match_submodule_name_or_type, _test_qat_wrapped_module, @@ -92,13 +93,9 @@ def test_quantization_oneshot(model_class): state = State(framework=Framework.pytorch, start_event=Event()) state.update(model=model) - strategy = "channel" - TORCH_VERSION = version.parse(torch.__version__) - if TORCH_VERSION.major < 2: # per channel quant only supported in 2+ - strategy = "tensor" scheme = dict( input_activations=dict(num_bits=8, symmetric=True), - weights=dict(num_bits=4, symmetric=False, strategy=strategy), + weights=dict(num_bits=4, symmetric=False, strategy="channel"), ) kwargs = dict(scheme=scheme) diff --git a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py index 31e9232d349..90a5068303f 100644 --- a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py +++ b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py @@ -15,6 +15,8 @@ import os import pytest +import torch +from packaging import version from torch.nn import Identity from sparseml.pytorch.sparsification.quantization.helpers import QATWrapper @@ -57,7 +59,15 @@ def _assert_observers_eq(observer_1, observer_2): if hasattr(observer_1, "p"): # assume observer is a partial, test by properties dict - assert observer_1.p.keywords == observer_2.p.keywords + observer_1_keywords = observer_1.p.keywords + observer_2_keywords = observer_2.p.keywords + TORCH_VERSION = version.parse(torch.__version__) + if ( + TORCH_VERSION.major < 2 + ): # can't match observer class instances before 2.0 + del observer_1_keywords["observer"] + del observer_2_keywords["observer"] + assert observer_1_keywords == observer_2_keywords else: # default to plain `==` assert observer_1 == observer_2 From 05e9e39ee0fc2b3350237f7e5b63a092ef6baceb Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 13:23:34 -0400 Subject: [PATCH 09/11] fix key error --- .../quantization/test_modifier_quantization.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py index 90a5068303f..6c412281d17 100644 --- a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py +++ b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py @@ -65,8 +65,9 @@ def _assert_observers_eq(observer_1, observer_2): if ( TORCH_VERSION.major < 2 ): # can't match observer class instances before 2.0 - del observer_1_keywords["observer"] - del observer_2_keywords["observer"] + if "observer" in observer_1_keywords: + del observer_1_keywords["observer"] + del observer_2_keywords["observer"] assert observer_1_keywords == observer_2_keywords else: # default to plain `==` From f07914251bc4bc37133459ac7171f0c0ed2bbd42 Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 13:33:14 -0400 Subject: [PATCH 10/11] bug fix for 1.9 --- .../sparsification/quantization/test_modifier_quantization.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py index 6c412281d17..175ac9dbff2 100644 --- a/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py +++ b/tests/sparseml/pytorch/sparsification/quantization/test_modifier_quantization.py @@ -67,6 +67,7 @@ def _assert_observers_eq(observer_1, observer_2): ): # can't match observer class instances before 2.0 if "observer" in observer_1_keywords: del observer_1_keywords["observer"] + if "observer" in observer_2_keywords: del observer_2_keywords["observer"] assert observer_1_keywords == observer_2_keywords else: From 85da44e39347b21e8df4dd1b39a8a52cc911105d Mon Sep 17 00:00:00 2001 From: Sara Adkins Date: Tue, 17 Oct 2023 15:44:47 -0400 Subject: [PATCH 11/11] move torch imports out of base quant --- src/sparseml/modifiers/quantization/base.py | 40 --------------- .../modifiers/quantization/pytorch.py | 50 ++++++++++++++++++- tests/sparseml/modifiers/__init__.py | 13 +++++ .../sparseml/{pytorch => }/modifiers/conf.py | 0 .../modifiers/quantization/__init__.py | 13 +++++ .../modifiers/quantization/test_base.py | 2 +- .../modifiers/quantization/test_pytorch.py | 5 +- 7 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 tests/sparseml/modifiers/__init__.py rename tests/sparseml/{pytorch => }/modifiers/conf.py (100%) create mode 100644 tests/sparseml/modifiers/quantization/__init__.py rename tests/sparseml/{pytorch => }/modifiers/quantization/test_base.py (97%) diff --git a/src/sparseml/modifiers/quantization/base.py b/src/sparseml/modifiers/quantization/base.py index 479b843815e..88f973beccc 100644 --- a/src/sparseml/modifiers/quantization/base.py +++ b/src/sparseml/modifiers/quantization/base.py @@ -15,10 +15,6 @@ from typing import Any, Dict, List, Optional from sparseml.core import Event, Modifier, State -from sparseml.modifiers.quantization.utils.quantization_scheme import ( - QuantizationScheme, - QuantizationSchemeLoadable, -) __all__ = ["QuantizationModifier"] @@ -57,15 +53,6 @@ class QuantizationModifier(Modifier): | model_fuse_fn_name: 'fuse_module' | strict: True - :param scheme: Default QuantizationScheme to use when enabling quantization - in a module. May also be a dictionary to be loaded into the QuantizationScheme - class. A string alias may also be used, supported aliases: - ['default', 'deepsparse', 'tensorrt']. - If None, the default scheme (`QuantizationScheme()`) will be used. - Default is None - :param scheme_overrides: optional mapping of module type names or submodule type - names to quantization schemes to override them with. If a scheme is mapped to - 'default', then it will use the scheme set in the modifier scheme property :param ignore: optional list of module class names or submodule names to not quantize. Default is None :param disable_quantization_observer_epoch: Epoch to disable updates to the module @@ -85,8 +72,6 @@ class QuantizationModifier(Modifier): scheme_overrides or ignore are not found in a given module. Default True """ - scheme: Optional[QuantizationSchemeLoadable] = None - scheme_overrides: Optional[Dict[str, QuantizationSchemeLoadable]] = None ignore: Optional[List[str]] = None disable_quantization_observer_epoch: Optional[float] = None freeze_bn_stats_epoch: Optional[float] = None @@ -98,10 +83,6 @@ class QuantizationModifier(Modifier): def __init__(self, **kwargs): super().__init__(**kwargs) - self.scheme = QuantizationScheme.load(self.scheme) - self.scheme_overrides = _load_quantization_schemes_dict( - self.scheme_overrides, self.scheme - ) if self.model_fuse_fn_kwargs is None: self.model_fuse_fn_kwargs = {} if self.ignore is None: @@ -158,24 +139,3 @@ def check_should_disable_observer(self, event: Event) -> bool: def on_initialize_structure(self, state: State, **kwargs): pass # nothing needed for this modifier - - -class _QuantizationSchemesDict(dict): - # wrapper class for dict to override the __str__ method for yaml serialization - - def __str__(self): - return str({submodule: scheme.dict() for submodule, scheme in self.items()}) - - -def _load_quantization_schemes_dict( - schemes_dict: Optional[Dict[str, QuantizationSchemeLoadable]], - default_scheme: QuantizationScheme, -) -> Dict[str, QuantizationScheme]: - if schemes_dict is None: - return {} - return _QuantizationSchemesDict( - { - submodule: QuantizationScheme.load(scheme, default=default_scheme) - for submodule, scheme in schemes_dict.items() - } - ) diff --git a/src/sparseml/modifiers/quantization/pytorch.py b/src/sparseml/modifiers/quantization/pytorch.py index 71b7d08d6fe..8a77bcb2eea 100644 --- a/src/sparseml/modifiers/quantization/pytorch.py +++ b/src/sparseml/modifiers/quantization/pytorch.py @@ -14,7 +14,7 @@ import logging from itertools import cycle -from typing import Any, Callable +from typing import Any, Callable, Dict, Optional import torch from torch.nn import Module @@ -26,6 +26,10 @@ freeze_bn_stats, fuse_module_conv_bn_relus, ) +from sparseml.modifiers.quantization.utils.quantization_scheme import ( + QuantizationScheme, + QuantizationSchemeLoadable, +) from sparseml.modifiers.quantization.utils.quantize import ( convert_module_qat_from_schemes, raise_if_torch_quantization_not_available, @@ -38,12 +42,35 @@ class QuantizationModifierPyTorch(QuantizationModifier): + """ + Pytorch-specific implementation of quantization modifier + + :param scheme: Default QuantizationScheme to use when enabling quantization + in a module. May also be a dictionary to be loaded into the QuantizationScheme + class. A string alias may also be used, supported aliases: + ['default', 'deepsparse', 'tensorrt']. + If None, the default scheme (`QuantizationScheme()`) will be used. + Default is None + :param scheme_overrides: optional mapping of module type names or submodule type + names to quantization schemes to override them with. If a scheme is mapped to + 'default', then it will use the scheme set in the modifier scheme property + """ + + scheme: Optional[QuantizationSchemeLoadable] = None + scheme_overrides: Optional[Dict[str, QuantizationSchemeLoadable]] = None calibration_dataloader_: Any = None calibration_function_: Any = None qat_enabled_: bool = False quantization_observer_disabled_: bool = False bn_stats_frozen_: bool = False + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.scheme = QuantizationScheme.load(self.scheme) + self.scheme_overrides = _load_quantization_schemes_dict( + self.scheme_overrides, self.scheme + ) + def on_initialize(self, state: State, **kwargs) -> bool: raise_if_torch_quantization_not_available() if self.end and self.end != -1: @@ -181,3 +208,24 @@ def _calibrate(self, module: Module): module.train() else: self._disable_quantization_observer(module) + + +class _QuantizationSchemesDict(dict): + # wrapper class for dict to override the __str__ method for yaml serialization + + def __str__(self): + return str({submodule: scheme.dict() for submodule, scheme in self.items()}) + + +def _load_quantization_schemes_dict( + schemes_dict: Optional[Dict[str, QuantizationSchemeLoadable]], + default_scheme: QuantizationScheme, +) -> Dict[str, QuantizationScheme]: + if schemes_dict is None: + return {} + return _QuantizationSchemesDict( + { + submodule: QuantizationScheme.load(scheme, default=default_scheme) + for submodule, scheme in schemes_dict.items() + } + ) diff --git a/tests/sparseml/modifiers/__init__.py b/tests/sparseml/modifiers/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/modifiers/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/pytorch/modifiers/conf.py b/tests/sparseml/modifiers/conf.py similarity index 100% rename from tests/sparseml/pytorch/modifiers/conf.py rename to tests/sparseml/modifiers/conf.py diff --git a/tests/sparseml/modifiers/quantization/__init__.py b/tests/sparseml/modifiers/quantization/__init__.py new file mode 100644 index 00000000000..0c44f887a47 --- /dev/null +++ b/tests/sparseml/modifiers/quantization/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2021 - present / Neuralmagic, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/sparseml/pytorch/modifiers/quantization/test_base.py b/tests/sparseml/modifiers/quantization/test_base.py similarity index 97% rename from tests/sparseml/pytorch/modifiers/quantization/test_base.py rename to tests/sparseml/modifiers/quantization/test_base.py index 5a238123590..cd5fab0e755 100644 --- a/tests/sparseml/pytorch/modifiers/quantization/test_base.py +++ b/tests/sparseml/modifiers/quantization/test_base.py @@ -16,7 +16,7 @@ from sparseml.core.factory import ModifierFactory from sparseml.core.framework import Framework from sparseml.modifiers.quantization import QuantizationModifier -from tests.sparseml.pytorch.modifiers.conf import setup_modifier_factory +from tests.sparseml.modifiers.conf import setup_modifier_factory def test_quantization_registered(): diff --git a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py index b7e84699cea..f9e686106bb 100644 --- a/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py +++ b/tests/sparseml/pytorch/modifiers/quantization/test_pytorch.py @@ -23,11 +23,8 @@ is_qat_helper_module, is_quantizable_module, ) +from tests.sparseml.modifiers.conf import LifecyleTestingHarness, setup_modifier_factory from tests.sparseml.pytorch.helpers import ConvNet, LinearNet -from tests.sparseml.pytorch.modifiers.conf import ( - LifecyleTestingHarness, - setup_modifier_factory, -) from tests.sparseml.pytorch.sparsification.quantization.test_modifier_quantization import ( # noqa E501 _match_submodule_name_or_type, _test_qat_wrapped_module,