accelforge 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- accelforge/__init__.py +21 -0
- accelforge/_accelerated_imports.py +16 -0
- accelforge/_deprecate/_simanneal/evalmapping.py +271 -0
- accelforge/_deprecate/_simanneal/mapspaceglobals.py +298 -0
- accelforge/_deprecate/_simanneal/simanneal.py +666 -0
- accelforge/_deprecate/_simanneal/tracking.py +105 -0
- accelforge/_deprecate/_simanneal/wrappers.py +218 -0
- accelforge/_deprecate/_simanneal2/__init__.py +7 -0
- accelforge/_deprecate/_simanneal2/simanneal.py +493 -0
- accelforge/_deprecate/_simanneal2/tracking.py +116 -0
- accelforge/_deprecate/compatibility_util.py +181 -0
- accelforge/_deprecate/layerdeduplication/__init__.py +2 -0
- accelforge/_deprecate/layerdeduplication/group_similar_einsums.py +160 -0
- accelforge/_deprecate/layerdeduplication/grouped_einsums.py +84 -0
- accelforge/_deprecate/mapping_filter_tags/__init__.py +2 -0
- accelforge/_deprecate/mapping_filter_tags/ffmt.py +212 -0
- accelforge/_deprecate/mapping_filter_tags/onesplit.py +24 -0
- accelforge/_deprecate/mapping_filter_tags/util.py +24 -0
- accelforge/_deprecate/tags.py +69 -0
- accelforge/_deprecate/viz/__init__.py +0 -0
- accelforge/_deprecate/viz/interactive.py +159 -0
- accelforge/_deprecate/viz/reservationtree.py +307 -0
- accelforge/_deprecate/viz/ski_slope.py +88 -0
- accelforge/_version.py +15 -0
- accelforge/examples.py +39 -0
- accelforge/frontend/__init__.py +10 -0
- accelforge/frontend/_binding.py +129 -0
- accelforge/frontend/_workload_isl/__init__.py +2 -0
- accelforge/frontend/_workload_isl/_isl.py +149 -0
- accelforge/frontend/_workload_isl/_symbolic.py +141 -0
- accelforge/frontend/arch copy.py +1544 -0
- accelforge/frontend/arch.py +1642 -0
- accelforge/frontend/config.py +63 -0
- accelforge/frontend/mapper/__init__.py +5 -0
- accelforge/frontend/mapper/ffm.py +126 -0
- accelforge/frontend/mapper/mapper.py +7 -0
- accelforge/frontend/mapper/metrics.py +30 -0
- accelforge/frontend/mapping/__init__.py +1 -0
- accelforge/frontend/mapping/mapping.py +1736 -0
- accelforge/frontend/model.py +14 -0
- accelforge/frontend/renames.py +150 -0
- accelforge/frontend/spec copy.py +230 -0
- accelforge/frontend/spec.py +301 -0
- accelforge/frontend/variables.py +12 -0
- accelforge/frontend/workload.py +952 -0
- accelforge/mapper/FFM/__init__.py +9 -0
- accelforge/mapper/FFM/_join_pmappings/__init__.py +0 -0
- accelforge/mapper/FFM/_join_pmappings/compatibility.py +653 -0
- accelforge/mapper/FFM/_join_pmappings/compress_pmappings.py +140 -0
- accelforge/mapper/FFM/_join_pmappings/join_pmappings.py +703 -0
- accelforge/mapper/FFM/_join_pmappings/pmapping_dataframe.py +901 -0
- accelforge/mapper/FFM/_join_pmappings/pmapping_group.py +337 -0
- accelforge/mapper/FFM/_make_pmappings/contraints/__init__.py +0 -0
- accelforge/mapper/FFM/_make_pmappings/contraints/constraints.py +360 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/__init__.py +1 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_loops.py +373 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_pmapping_templates.py +463 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_reservations.py +95 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_storage_order.py +382 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmapping_templates/make_storages.py +155 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings.py +411 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/__init__.py +1 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/make_pmappings_from_templates.py +407 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/make_tile_shapes.py +1681 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/run_model.py +170 -0
- accelforge/mapper/FFM/_make_pmappings/make_pmappings_from_templates/symbol_relations.py +174 -0
- accelforge/mapper/FFM/_make_pmappings/pmapper_job.py +282 -0
- accelforge/mapper/FFM/_pareto_df/df_convention.py +273 -0
- accelforge/mapper/FFM/_pareto_df/pareto copy.py +836 -0
- accelforge/mapper/FFM/_pareto_df/pareto.py +508 -0
- accelforge/mapper/FFM/data.py +61 -0
- accelforge/mapper/FFM/main copy.py +236 -0
- accelforge/mapper/FFM/main.py +208 -0
- accelforge/mapper/FFM/mappings.py +510 -0
- accelforge/mapper/FFM/pmappings.py +310 -0
- accelforge/mapper/__init__.py +4 -0
- accelforge/mapper.py +0 -0
- accelforge/model/__init__.py +1 -0
- accelforge/model/_looptree/__init__.py +0 -0
- accelforge/model/_looptree/accesses.py +335 -0
- accelforge/model/_looptree/capacity/__init__.py +1 -0
- accelforge/model/_looptree/capacity/aggregators.py +36 -0
- accelforge/model/_looptree/capacity/capacity.py +47 -0
- accelforge/model/_looptree/energy.py +150 -0
- accelforge/model/_looptree/equivalent_ranks.py +29 -0
- accelforge/model/_looptree/latency/__init__.py +1 -0
- accelforge/model/_looptree/latency/latency.py +98 -0
- accelforge/model/_looptree/latency/memory.py +120 -0
- accelforge/model/_looptree/latency/processors.py +92 -0
- accelforge/model/_looptree/mapping_utilities.py +71 -0
- accelforge/model/_looptree/reuse/__init__.py +4 -0
- accelforge/model/_looptree/reuse/isl/__init__.py +1 -0
- accelforge/model/_looptree/reuse/isl/des.py +59 -0
- accelforge/model/_looptree/reuse/isl/isl_functions.py +374 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/__init__.py +4 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/analyze_mapping.py +297 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/skews_from_mapping.py +236 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/tiling.py +685 -0
- accelforge/model/_looptree/reuse/isl/mapping_to_isl/types.py +188 -0
- accelforge/model/_looptree/reuse/isl/spatial.py +260 -0
- accelforge/model/_looptree/reuse/isl/temporal.py +182 -0
- accelforge/model/_looptree/reuse/symbolic/__init__.py +1 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic copy 2.py +1346 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic copy.py +1408 -0
- accelforge/model/_looptree/reuse/symbolic/symbolic.py +1396 -0
- accelforge/model/_looptree/run.py +122 -0
- accelforge/model/_looptree/types.py +26 -0
- accelforge/model/_looptree/visualization/__init__.py +0 -0
- accelforge/model/_looptree/visualization/occupancy.py +11 -0
- accelforge/model/main.py +222 -0
- accelforge/plotting/__init__.py +2 -0
- accelforge/plotting/mappings.py +219 -0
- accelforge/plotting/specs.py +57 -0
- accelforge/util/__init__.py +4 -0
- accelforge/util/_base_analysis_types.py +24 -0
- accelforge/util/_basetypes.py +1089 -0
- accelforge/util/_frozenset.py +36 -0
- accelforge/util/_isl.py +29 -0
- accelforge/util/_itertools.py +14 -0
- accelforge/util/_mathfuncs.py +57 -0
- accelforge/util/_parse_expressions.py +339 -0
- accelforge/util/_picklecache.py +32 -0
- accelforge/util/_setexpressions.py +268 -0
- accelforge/util/_sympy/__init__.py +0 -0
- accelforge/util/_sympy/broadcast_max.py +18 -0
- accelforge/util/_visualization.py +112 -0
- accelforge/util/_yaml.py +579 -0
- accelforge/util/parallel.py +193 -0
- accelforge-0.0.1.dist-info/METADATA +64 -0
- accelforge-0.0.1.dist-info/RECORD +258 -0
- accelforge-0.0.1.dist-info/WHEEL +5 -0
- accelforge-0.0.1.dist-info/licenses/LICENSE +19 -0
- accelforge-0.0.1.dist-info/top_level.txt +5 -0
- docs/_build/html/_sources/fastfusion.frontend.mapper.rst.txt +37 -0
- docs/_build/html/_sources/fastfusion.frontend.rst.txt +70 -0
- docs/_build/html/_sources/fastfusion.frontend.workload.rst.txt +21 -0
- docs/_build/html/_sources/fastfusion.mapper.FFM.rst.txt +37 -0
- docs/_build/html/_sources/fastfusion.mapper.rst.txt +18 -0
- docs/_build/html/_sources/fastfusion.rst.txt +20 -0
- docs/_build/html/_sources/fastfusion.util.rst.txt +21 -0
- docs/_build/html/_sources/index.rst.txt +87 -0
- docs/_build/html/_sources/modules.rst.txt +7 -0
- docs/_build/html/_sources/notes/citation.rst.txt +45 -0
- docs/_build/html/_sources/notes/definitions.rst.txt +43 -0
- docs/_build/html/_sources/notes/faqs.rst.txt +39 -0
- docs/_build/html/_sources/notes/modeling/accelerator_energy_latency.rst.txt +72 -0
- docs/_build/html/_sources/notes/modeling/component_energy_area.rst.txt +96 -0
- docs/_build/html/_sources/notes/modeling/mapping.rst.txt +100 -0
- docs/_build/html/_sources/notes/modeling.rst.txt +33 -0
- docs/_build/html/_sources/notes/parsing/arithmetic_parsing.rst.txt +136 -0
- docs/_build/html/_sources/notes/parsing/setexpressions.rst.txt +63 -0
- docs/_build/html/_sources/notes/parsing/yaml_parsing.rst.txt +176 -0
- docs/_build/html/_sources/notes/quickstart_and_installation.rst.txt +9 -0
- docs/_build/html/_sources/notes/spec/architecture.rst.txt +133 -0
- docs/_build/html/_sources/notes/spec/mapping.rst.txt +12 -0
- docs/_build/html/_sources/notes/spec/workload.rst.txt +83 -0
- docs/_build/html/_sources/notes/spec.rst.txt +36 -0
- docs/source/_ext/include_attrs.py +213 -0
- docs/source/_ext/include_docstring.py +364 -0
- docs/source/_ext/include_functions.py +154 -0
- docs/source/_ext/include_notebook.py +131 -0
- docs/source/_ext/include_yaml.py +119 -0
- docs/source/_ext/inherited_attributes.py +222 -0
- docs/source/_ext/paths.py +4 -0
- docs/source/conf.py +79 -0
- examples/arches/compute_in_memory/_include.yaml +74 -0
- examples/arches/compute_in_memory/_include_functions.py +229 -0
- examples/arches/compute_in_memory/_load_spec.py +57 -0
- examples/arches/compute_in_memory/components/c2c_multiplier.py +181 -0
- examples/arches/compute_in_memory/components/dac_c2c_r2r.py +605 -0
- examples/arches/compute_in_memory/components/misc.py +195 -0
- examples/arches/compute_in_memory/components/util/bit_functions.py +51 -0
- examples/arches/compute_in_memory/components/zero_comparator.py +92 -0
- examples/arches/compute_in_memory/isaac.yaml +233 -0
- examples/arches/compute_in_memory/memory_cells/ecram_demo.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_example.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_isaac_isca_2016.yaml +64 -0
- examples/arches/compute_in_memory/memory_cells/rram_neurosim_default.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/rram_raella_isca_2023.yaml +70 -0
- examples/arches/compute_in_memory/memory_cells/rram_wan_nature_2022.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_colonnade_jssc_2021.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_example.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_jia_jssc_2020.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_sinangil_jssc_2021.yaml +63 -0
- examples/arches/compute_in_memory/memory_cells/sram_wang_vlsi_2022.yaml +63 -0
- examples/arches/compute_in_memory/wang_vlsi_2022.yaml +289 -0
- examples/arches/eyeriss.yaml +68 -0
- examples/arches/fanout_variations/at_glb.yaml +31 -0
- examples/arches/fanout_variations/at_glb_with_fanout_node.yaml +34 -0
- examples/arches/fanout_variations/at_mac.yaml +31 -0
- examples/arches/fanout_variations/at_mac_with_constraints.yaml +38 -0
- examples/arches/fanout_variations/at_mac_with_fanout_node.yaml +34 -0
- examples/arches/nvdla.yaml +47 -0
- examples/arches/simple.yaml +28 -0
- examples/arches/tpu_v4i.yaml +67 -0
- examples/mappings/unfused_matmuls_to_simple.yaml +33 -0
- examples/misc/component_annotated.yaml +33 -0
- examples/workloads/gpt3_6.7B.yaml +124 -0
- examples/workloads/matmuls.yaml +20 -0
- examples/workloads/mobilenet_28.yaml +81 -0
- examples/workloads/mobilenet_various_separate.yaml +106 -0
- examples/workloads/three_matmuls_annotated.yaml +59 -0
- notebooks/.ipynb_checkpoints/fastfusion_arch_study_michael-checkpoint.ipynb +359 -0
- notebooks/compute_in_memory/_scripts.py +339 -0
- notebooks/compute_in_memory/isaac.guide.ipynb +270 -0
- notebooks/compute_in_memory/wang_vlsi_2022.ipynb +602 -0
- notebooks/paths.py +4 -0
- notebooks/tutorials/.ipynb_checkpoints/1_FFM-checkpoint.ipynb +3110 -0
- notebooks/tutorials/FFM.ipynb +3498 -0
- notebooks/tutorials/_include.py +48 -0
- notebooks/tutorials/component_energy_area.ipynb +363 -0
- tests/Q_mapping.yaml +38 -0
- tests/__init__.py +0 -0
- tests/conv.mapping.yaml +27 -0
- tests/conv.workload.yaml +13 -0
- tests/conv_sym.mapping.yaml +43 -0
- tests/copy.mapping.yaml +35 -0
- tests/copy.workload.yaml +15 -0
- tests/distribuffers/__init__.py +0 -0
- tests/distribuffers/multicast/test_cases.yaml +482 -0
- tests/distribuffers/spec/binding/valid_bindings.yaml +97 -0
- tests/distribuffers/spec/distributed.yaml +100 -0
- tests/distribuffers/spec/logical_arch.yaml +32 -0
- tests/distribuffers/spec/physical_arch.yaml +69 -0
- tests/distribuffers/test_binding.py +48 -0
- tests/frontend/__init__.py +0 -0
- tests/frontend/test_mapping_viz.py +52 -0
- tests/mapper/__init__.py +0 -0
- tests/mapper/configs/conv1d/conv1d.mapping.yaml +31 -0
- tests/mapper/configs/conv1d/conv1d.workload.yaml +11 -0
- tests/mapper/configs/two_conv1d/two_conv1d.expected.yaml +38 -0
- tests/mapper/configs/two_conv1d/two_conv1d.mapping.yaml +54 -0
- tests/mapper/configs/two_conv1d/two_conv1d.workload.yaml +19 -0
- tests/mapper/test_mapping_to_isl.py +90 -0
- tests/mapper/test_spatial_reuse_analysis.py +67 -0
- tests/mapper/test_temporal_reuse_analysis.py +56 -0
- tests/mapper/util.py +58 -0
- tests/matmul.mapping.yaml +29 -0
- tests/matmul.workload.yaml +12 -0
- tests/matmul_spatial.mapping.yaml +44 -0
- tests/mha.renames.yaml +65 -0
- tests/mha.workload.yaml +67 -0
- tests/mha.yaml +59 -0
- tests/mha_full.workload.yaml +67 -0
- tests/mobilenet.workload.yaml +35 -0
- tests/mobilenet_long.workload.yaml +64 -0
- tests/pmappingcache.py +24 -0
- tests/processing_stage.arch.yaml +40 -0
- tests/snowcat.arch.yaml +36 -0
- tests/test_ffm_join_pmappings.py +106 -0
- tests/test_ffm_make_pmappings.py +82 -0
- tests/test_ffm_make_tile_shapes.py +49 -0
- tests/test_mapper.py +100 -0
- tests/test_model.py +37 -0
- tests/test_plotting.py +72 -0
- tests/test_processing_stage.py +46 -0
- tests/test_symbolic_model.py +248 -0
- tests/test_workload.py +141 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
arch:
|
|
2
|
+
nodes:
|
|
3
|
+
- !Component
|
|
4
|
+
name: DRAM # offchip DRAM is the source of all datatypes
|
|
5
|
+
class: DRAM # assume DRAM is large enough to store all the data, so no depth specification needed
|
|
6
|
+
attributes:
|
|
7
|
+
width: 64 # width in bits
|
|
8
|
+
|
|
9
|
+
- !Container
|
|
10
|
+
name: PE
|
|
11
|
+
spatial: {meshX: 1, meshY: 2}
|
|
12
|
+
|
|
13
|
+
# registers for the mac unit
|
|
14
|
+
- !Component
|
|
15
|
+
name: weight_reg
|
|
16
|
+
class: reg_storage
|
|
17
|
+
attributes: {depth: 1, width: 8}
|
|
18
|
+
|
|
19
|
+
- !Component
|
|
20
|
+
name: input_activation_reg
|
|
21
|
+
class: reg_storage
|
|
22
|
+
attributes: {depth: 1, width: 8}
|
|
23
|
+
|
|
24
|
+
- !Component
|
|
25
|
+
name: output_activation_reg
|
|
26
|
+
class: reg_storage
|
|
27
|
+
attributes: {depth: 1, width: 8}
|
|
28
|
+
|
|
29
|
+
- !Component
|
|
30
|
+
name: mac
|
|
31
|
+
class: mac_compute
|
|
32
|
+
attributes: {num_pipline_stages: 2}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
arch:
|
|
2
|
+
name: "test_distributed_spec"
|
|
3
|
+
nodes:
|
|
4
|
+
- !Container
|
|
5
|
+
name: system_arch
|
|
6
|
+
attributes:
|
|
7
|
+
# Top-level attributes inherited by all components unless overridden
|
|
8
|
+
technology: "45nm"
|
|
9
|
+
cycle_period: 1e-9
|
|
10
|
+
|
|
11
|
+
- !Network
|
|
12
|
+
name: L2
|
|
13
|
+
topology: Mesh
|
|
14
|
+
dims:
|
|
15
|
+
- x
|
|
16
|
+
constraints:
|
|
17
|
+
- 0 <= x < 2
|
|
18
|
+
- !Network
|
|
19
|
+
name: L1
|
|
20
|
+
topology: Mesh
|
|
21
|
+
dims:
|
|
22
|
+
- x
|
|
23
|
+
- y
|
|
24
|
+
constraints:
|
|
25
|
+
- 0 <= x < 1
|
|
26
|
+
- -1 <= y <= 1
|
|
27
|
+
port: |
|
|
28
|
+
{L2[x] -> L1[x', y'] : x = 1 and x' = 0 and y' = 0}
|
|
29
|
+
|
|
30
|
+
- !Component
|
|
31
|
+
name: DRAM # offchip DRAM is the source of all datatypes
|
|
32
|
+
class: DRAM # assume DRAM is large enough to store all the data, so no depth specification needed
|
|
33
|
+
attributes:
|
|
34
|
+
width: 64 # width in bits
|
|
35
|
+
network:
|
|
36
|
+
level: L2
|
|
37
|
+
placement: "{ DRAM[i] -> L2[i] | i = 1 }"
|
|
38
|
+
|
|
39
|
+
- !Container
|
|
40
|
+
name: PE
|
|
41
|
+
network:
|
|
42
|
+
level: L1
|
|
43
|
+
placement: |
|
|
44
|
+
{
|
|
45
|
+
PE[i, j] -> L1[x, y] :
|
|
46
|
+
j = y and x < 0 and i = -x - 1;
|
|
47
|
+
j = y and x > 0 and i = x;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# registers for the mac unit
|
|
51
|
+
- !Component
|
|
52
|
+
name: weight_reg
|
|
53
|
+
class: reg_storage
|
|
54
|
+
attributes: {depth: 1, width: 8}
|
|
55
|
+
|
|
56
|
+
- !Component
|
|
57
|
+
name: input_activation_reg
|
|
58
|
+
class: reg_storage
|
|
59
|
+
attributes: {depth: 1, width: 8}
|
|
60
|
+
|
|
61
|
+
- !Component
|
|
62
|
+
name: output_activation_reg
|
|
63
|
+
class: reg_storage
|
|
64
|
+
attributes: {depth: 1, width: 8}
|
|
65
|
+
|
|
66
|
+
- !Component
|
|
67
|
+
name: mac
|
|
68
|
+
class: mac_compute
|
|
69
|
+
attributes: {num_pipline_stages: 2}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
from typing import Dict, List
|
|
5
|
+
from islpy import DEFAULT_CONTEXT, Map
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
from accelforge.frontend._binding import Binding, BindingNode
|
|
9
|
+
|
|
10
|
+
TESTS_DIR = Path(__file__).parent / "spec" / "binding"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestBindingMapper(unittest.TestCase):
|
|
14
|
+
def test_valid_bindings(self):
|
|
15
|
+
"""
|
|
16
|
+
Tests that the valid bindings translate into the appropriate
|
|
17
|
+
ISL strings.
|
|
18
|
+
"""
|
|
19
|
+
specs_file: str = TESTS_DIR / "valid_bindings.yaml"
|
|
20
|
+
with open(specs_file, mode="r", encoding="utf-8") as f:
|
|
21
|
+
specs: List = yaml.safe_load(f)
|
|
22
|
+
|
|
23
|
+
spec: Dict
|
|
24
|
+
for spec in specs:
|
|
25
|
+
binding: Binding = Binding.model_validate(spec["binding"])
|
|
26
|
+
|
|
27
|
+
soln: Dict = spec["solution"]
|
|
28
|
+
|
|
29
|
+
soln_node: Dict[str, str]
|
|
30
|
+
binding_node: BindingNode
|
|
31
|
+
for soln_node, binding_node in zip(soln["nodes"], binding.nodes):
|
|
32
|
+
isl_relations: Dict[str, Map] = binding_node.isl_relations
|
|
33
|
+
assert soln_node.keys() == isl_relations.keys(), (
|
|
34
|
+
"Not all isl_relations read in properly. Missing \n"
|
|
35
|
+
f"{set(soln_node.keys()).difference(isl_relations.keys())} "
|
|
36
|
+
"\nfrom isl_relations and \n"
|
|
37
|
+
f"{set(isl_relations.keys()).difference(soln_node.keys())} "
|
|
38
|
+
"\nfrom solutions.\n"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
tensor: str
|
|
42
|
+
for tensor in soln_node:
|
|
43
|
+
soln_relation: Map = Map.read_from_str(
|
|
44
|
+
DEFAULT_CONTEXT, soln_node[tensor]
|
|
45
|
+
)
|
|
46
|
+
assert soln_relation.is_equal(
|
|
47
|
+
isl_relations[tensor]
|
|
48
|
+
), f"\n{soln_relation} != \n{isl_relations[tensor]}"
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Uncommenting the lines with `graph.write_png` will generate PNG pictures of
|
|
3
|
+
LoopTrees so they can be inspected.
|
|
4
|
+
|
|
5
|
+
TODO: an automated way to check for correctness.
|
|
6
|
+
"""
|
|
7
|
+
import unittest
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from accelforge.frontend.spec import Spec
|
|
11
|
+
from accelforge.model.main import evaluate_mapping
|
|
12
|
+
from accelforge.util.parallel import set_n_parallel_jobs
|
|
13
|
+
|
|
14
|
+
set_n_parallel_jobs(1)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
EXAMPLES_DIR = Path(__file__).parent.parent.parent / "examples"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestModel(unittest.TestCase):
|
|
21
|
+
def test_default(self):
|
|
22
|
+
spec = Spec.from_yaml(
|
|
23
|
+
EXAMPLES_DIR / "arches" / "simple.yaml",
|
|
24
|
+
EXAMPLES_DIR / "workloads" / "matmuls.yaml",
|
|
25
|
+
EXAMPLES_DIR / "mappings" / "unfused_matmuls_to_simple.yaml",
|
|
26
|
+
jinja_parse_data={"N_EINSUMS": 2, "M": 64, "KN": 64},
|
|
27
|
+
)
|
|
28
|
+
result = evaluate_mapping(spec)
|
|
29
|
+
graph = result.data["Total<SEP>mapping"].iloc[0]().render_pydot()
|
|
30
|
+
# graph.write_png("default.png")
|
|
31
|
+
|
|
32
|
+
def test_without_reservations(self):
|
|
33
|
+
spec = Spec.from_yaml(
|
|
34
|
+
EXAMPLES_DIR / "arches" / "simple.yaml",
|
|
35
|
+
EXAMPLES_DIR / "workloads" / "matmuls.yaml",
|
|
36
|
+
EXAMPLES_DIR / "mappings" / "unfused_matmuls_to_simple.yaml",
|
|
37
|
+
jinja_parse_data={"N_EINSUMS": 2, "M": 64, "KN": 64},
|
|
38
|
+
)
|
|
39
|
+
result = evaluate_mapping(spec)
|
|
40
|
+
graph = result.data["Total<SEP>mapping"].iloc[0]().render_pydot(with_reservations=False)
|
|
41
|
+
# graph.write_png("without_reservations.png")
|
|
42
|
+
|
|
43
|
+
def test_without_stride(self):
|
|
44
|
+
spec = Spec.from_yaml(
|
|
45
|
+
EXAMPLES_DIR / "arches" / "simple.yaml",
|
|
46
|
+
EXAMPLES_DIR / "workloads" / "matmuls.yaml",
|
|
47
|
+
EXAMPLES_DIR / "mappings" / "unfused_matmuls_to_simple.yaml",
|
|
48
|
+
jinja_parse_data={"N_EINSUMS": 2, "M": 64, "KN": 64},
|
|
49
|
+
)
|
|
50
|
+
result = evaluate_mapping(spec)
|
|
51
|
+
graph = result.data["Total<SEP>mapping"].iloc[0]().render_pydot(with_tile_shape=False)
|
|
52
|
+
# graph.write_png("without_stride.png")
|
tests/mapper/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
mapping:
|
|
2
|
+
nodes:
|
|
3
|
+
- !Storage
|
|
4
|
+
tensors: [I, W, O]
|
|
5
|
+
component: MainMemory
|
|
6
|
+
- !Temporal
|
|
7
|
+
rank_variable: p
|
|
8
|
+
# bound is 2
|
|
9
|
+
tile_pattern:
|
|
10
|
+
initial_tile_shape: 8
|
|
11
|
+
stride: 8
|
|
12
|
+
- !Storage
|
|
13
|
+
tensors: [I, W, O]
|
|
14
|
+
component: LocalBuffer
|
|
15
|
+
- !Temporal
|
|
16
|
+
rank_variable: p
|
|
17
|
+
# bound is 8
|
|
18
|
+
tile_pattern:
|
|
19
|
+
initial_tile_shape: 1
|
|
20
|
+
stride: 1
|
|
21
|
+
- !Spatial
|
|
22
|
+
rank_variable: r
|
|
23
|
+
# bound is 3
|
|
24
|
+
tile_pattern:
|
|
25
|
+
initial_tile_shape: 1
|
|
26
|
+
stride: 1
|
|
27
|
+
component: MAC
|
|
28
|
+
name: X
|
|
29
|
+
- !Compute
|
|
30
|
+
einsum: conv
|
|
31
|
+
compute: MAC
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
mapping_to_isl:
|
|
2
|
+
BufferTensorEinsum(buffer='MainMemory', tensor='I', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
3
|
+
{ MainMemory_spacetime[] -> I[PI] : 0 <= PI < 18 }
|
|
4
|
+
BufferTensorEinsum(buffer='MainMemory', tensor='WA', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
5
|
+
{ MainMemory_spacetime[] -> WA[RA] : 0 <= RA < 3 }
|
|
6
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='I', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
7
|
+
{ LocalBuffer_spacetime[pb0=0] -> I[PI] : 0 <= PI < 12;
|
|
8
|
+
LocalBuffer_spacetime[pb0=1] -> I[PI] : 10 <= PI < 18 }
|
|
9
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='WA', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
10
|
+
{ LocalBuffer_spacetime[pb0] -> WA[RA] : 0 <= RA <= 2 and 0 <= pb0 < 2 }
|
|
11
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='A', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
12
|
+
{ LocalBuffer_spacetime[pb0=0] -> A[PA] : 0 <= PA < 10;
|
|
13
|
+
LocalBuffer_spacetime[pb0=1] -> A[PA] : 10 <= PA < 16 }
|
|
14
|
+
BufferTensorEinsum(buffer='MAC', tensor='I', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
15
|
+
{ MAC_spacetime[pb0=0, 0, pa1, ra0] -> I[PI = pa1 + ra0] : 0 <= pa1 < 10 and 0 <= ra0 < 3;
|
|
16
|
+
MAC_spacetime[pb0=1, 0, pa1, ra0] -> I[PA = 10 + pa1 + ra0] : 0 <= pa1 < 6 and 0 <= ra0 < 3 }
|
|
17
|
+
BufferTensorEinsum(buffer='MAC', tensor='WA', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
18
|
+
{ MAC_spacetime[pb0=0, 0, pa1, ra0] -> WA[RA=ra0] : 0 <= pa1 < 10 and 0 <= ra0 < 3;
|
|
19
|
+
MAC_spacetime[pb0=1, 0, pa1, ra0] -> WA[RA=ra0] : 0 <= pa1 < 6 and 0 <= ra0 < 3 }
|
|
20
|
+
BufferTensorEinsum(buffer='MAC', tensor='A', einsum=Compute(type=None, einsum='convA', compute='MAC', component_object=None)): |
|
|
21
|
+
{ MAC_spacetime[pb0=0, 0, pa1, ra0] -> A[PA=pa1] : 0 <= pa1 < 10 and 0 <= ra0 < 3;
|
|
22
|
+
MAC_spacetime[pb0=1, 0, pa1, ra0] -> A[PA=10 + pa1] : 0 <= pa1 < 6 and 0 <= ra0 < 3 }
|
|
23
|
+
BufferTensorEinsum(buffer='MainMemory', tensor='WB', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
24
|
+
{ MainMemory_spacetime[] -> WB[RB] : 0 <= RB < 3 }
|
|
25
|
+
BufferTensorEinsum(buffer='MainMemory', tensor='B', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
26
|
+
{ MainMemory_spacetime[] -> B[PB] : 0 <= PB < 16 }
|
|
27
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='A', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
28
|
+
{ LocalBuffer_spacetime[pb0] -> A[PA] : 0 <= pb0 < 2 and 8pb0 <= PA <= 9 + 8pb0 }
|
|
29
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='B', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
30
|
+
{ LocalBuffer_spacetime[pb0] -> B[PB] : 0 <= pb0 < 2 and 8pb0 <= PB < 8 + 8pb0 }
|
|
31
|
+
BufferTensorEinsum(buffer='LocalBuffer', tensor='WB', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
32
|
+
{ LocalBuffer_spacetime[pb0] -> WB[RB] : 0 <= pb0 < 2 and 0 <= RB <= 2 }
|
|
33
|
+
BufferTensorEinsum(buffer='MAC', tensor='A', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
34
|
+
{ MAC_spacetime[pb0, 1, pb2, rb0] -> A[PA = 8pb0 + pb2 + rb0] : 0 <= pb0 <= 1 and 0 <= pb2 <= 7 and 0 <= rb0 <= 2 }
|
|
35
|
+
BufferTensorEinsum(buffer='MAC', tensor='WB', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
36
|
+
{ MAC_spacetime[pb0, 1, pb2, rb0] -> WB[RB = rb0] : 0 <= pb0 <= 1 and 0 <= pb2 <= 7 and 0 <= rb0 <= 2 }
|
|
37
|
+
BufferTensorEinsum(buffer='MAC', tensor='B', einsum=Compute(type=None, einsum='convB', compute='MAC', component_object=None)): |
|
|
38
|
+
{ MAC_spacetime[pb0, 1, pb2, rb0] -> B[PB = 8pb0 + pb2] : 0 <= pb0 <= 1 and 0 <= pb2 <= 7 and 0 <= rb0 <= 2 }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
mapping:
|
|
2
|
+
nodes:
|
|
3
|
+
- !Storage
|
|
4
|
+
tensors: [I, WA, WB, B]
|
|
5
|
+
component: MainMemory
|
|
6
|
+
- !Temporal
|
|
7
|
+
rank_variable: pb
|
|
8
|
+
# bound is 2
|
|
9
|
+
tile_pattern:
|
|
10
|
+
initial_tile_shape: 8
|
|
11
|
+
stride: 8
|
|
12
|
+
- !Storage
|
|
13
|
+
tensors: [I, WA, A, WB, B]
|
|
14
|
+
component: LocalBuffer
|
|
15
|
+
- !Sequential
|
|
16
|
+
nodes:
|
|
17
|
+
- !Nested
|
|
18
|
+
nodes:
|
|
19
|
+
- !Temporal
|
|
20
|
+
rank_variable: pa
|
|
21
|
+
# bound is 8
|
|
22
|
+
tile_pattern:
|
|
23
|
+
initial_tile_shape: 1
|
|
24
|
+
stride: 1
|
|
25
|
+
- !Spatial
|
|
26
|
+
rank_variable: ra
|
|
27
|
+
# bound is 3
|
|
28
|
+
tile_pattern:
|
|
29
|
+
initial_tile_shape: 1
|
|
30
|
+
stride: 1
|
|
31
|
+
component: MAC
|
|
32
|
+
name: X
|
|
33
|
+
- !Compute
|
|
34
|
+
einsum: convA
|
|
35
|
+
compute: MAC
|
|
36
|
+
- !Nested
|
|
37
|
+
nodes:
|
|
38
|
+
- !Temporal
|
|
39
|
+
rank_variable: pb
|
|
40
|
+
# bound is 8
|
|
41
|
+
tile_pattern:
|
|
42
|
+
initial_tile_shape: 1
|
|
43
|
+
stride: 1
|
|
44
|
+
- !Spatial
|
|
45
|
+
rank_variable: rb
|
|
46
|
+
# bound is 3
|
|
47
|
+
tile_pattern:
|
|
48
|
+
initial_tile_shape: 1
|
|
49
|
+
stride: 1
|
|
50
|
+
component: MAC
|
|
51
|
+
name: X
|
|
52
|
+
- !Compute
|
|
53
|
+
einsum: convB
|
|
54
|
+
compute: MAC
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
workload:
|
|
2
|
+
shape:
|
|
3
|
+
ra: 0 <= ra < 3
|
|
4
|
+
pa: 0 <= pa < 16
|
|
5
|
+
rb: 0 <= rb < 3
|
|
6
|
+
pb: 0 <= pb < 16
|
|
7
|
+
|
|
8
|
+
einsums:
|
|
9
|
+
- name: convA
|
|
10
|
+
tensor_accesses:
|
|
11
|
+
- {name: I, projection: { PI: pa+ra }}
|
|
12
|
+
- {name: WA, projection: [ ra ]}
|
|
13
|
+
- {name: A, projection: [ pa ], output: True}
|
|
14
|
+
|
|
15
|
+
- name: convB
|
|
16
|
+
tensor_accesses:
|
|
17
|
+
- {name: A, projection: { PA: pb+rb }}
|
|
18
|
+
- {name: WB, projection: [ rb ]}
|
|
19
|
+
- {name: B, projection: [ pb ], output: True}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Some non-exhaustive tests to make sure core functionality of the non-fusing and
|
|
3
|
+
fusing portions of ISL tiling is not violated under changes.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from pprint import pformat
|
|
8
|
+
import unittest
|
|
9
|
+
|
|
10
|
+
import islpy as isl
|
|
11
|
+
|
|
12
|
+
from accelforge.frontend.workload import Workload
|
|
13
|
+
from accelforge.frontend.mapping import Mapping
|
|
14
|
+
|
|
15
|
+
from accelforge.model._looptree.reuse.isl.mapping_to_isl import analyze_mapping
|
|
16
|
+
from accelforge.model._looptree.reuse.isl.mapping_to_isl.types import (
|
|
17
|
+
MappingAnalysisResult,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .util import TEST_CONFIG_PATH, load_solutions
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TestMappingToIsl(unittest.TestCase):
|
|
24
|
+
"""
|
|
25
|
+
Tests taking a `Mapping` and `Workload` and converting it into relevant isl
|
|
26
|
+
objects.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def test_conv1d(self):
|
|
30
|
+
"""
|
|
31
|
+
Non-fusing one 1-dimensional convolution test.
|
|
32
|
+
"""
|
|
33
|
+
# Loads in the CONV1D Config
|
|
34
|
+
config_path: Path = TEST_CONFIG_PATH / "conv1d"
|
|
35
|
+
workload: Workload = Workload.from_yaml(config_path / "conv1d.workload.yaml")
|
|
36
|
+
|
|
37
|
+
mapping: Mapping = Mapping.from_yaml(config_path / "conv1d.mapping.yaml")
|
|
38
|
+
occupancies: MappingAnalysisResult = analyze_mapping.occupancies_from_mapping(
|
|
39
|
+
mapping, workload
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
for buffer, occupancy in occupancies.buffet_to_occupancy.items():
|
|
43
|
+
if buffer == list(occupancies.buffet_to_occupancy.keys())[-1]:
|
|
44
|
+
soln: isl.Map = isl.Map.read_from_str(
|
|
45
|
+
isl.DEFAULT_CONTEXT,
|
|
46
|
+
"{ MAC_spacetime[P1, P0, R] -> O[P=8*P1 + P0] : "
|
|
47
|
+
"0 <= R < 3 and 0 <= P1 < 2 and 0 <= P0 < 8}",
|
|
48
|
+
)
|
|
49
|
+
assert occupancy.map_ == soln
|
|
50
|
+
|
|
51
|
+
def test_two_conv1d(self):
|
|
52
|
+
"""
|
|
53
|
+
Fusing two 1-dimensional convolutions test.
|
|
54
|
+
"""
|
|
55
|
+
# Loads in the CONV1D Config
|
|
56
|
+
config_path: Path = TEST_CONFIG_PATH / "two_conv1d"
|
|
57
|
+
workload: Workload = Workload.from_yaml(
|
|
58
|
+
config_path / "two_conv1d.workload.yaml"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
mapping: Mapping = Mapping.from_yaml(config_path / "two_conv1d.mapping.yaml")
|
|
62
|
+
occupancies: MappingAnalysisResult = analyze_mapping.occupancies_from_mapping(
|
|
63
|
+
mapping, workload
|
|
64
|
+
)
|
|
65
|
+
solns: dict = load_solutions(config_path / "two_conv1d.expected.yaml")[
|
|
66
|
+
"mapping_to_isl"
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
errors: list = []
|
|
70
|
+
buffers_seen: set = set()
|
|
71
|
+
for buffer, occupancy in occupancies.buffet_to_occupancy.items():
|
|
72
|
+
try:
|
|
73
|
+
soln = solns[repr(buffer)]
|
|
74
|
+
assert (
|
|
75
|
+
occupancy.map_ == soln
|
|
76
|
+
), f"{buffer} should hold:\n{soln}\ninstead holds:\n{occupancy.map_}"
|
|
77
|
+
except (AssertionError, KeyError) as e:
|
|
78
|
+
errors.append(e)
|
|
79
|
+
buffers_seen.add(repr(buffer))
|
|
80
|
+
|
|
81
|
+
buffers_known: set = set(solns.keys())
|
|
82
|
+
try:
|
|
83
|
+
assert buffers_seen == buffers_known, (
|
|
84
|
+
f"Buffers Missing: {pformat(buffers_seen - buffers_known)}\n"
|
|
85
|
+
f"Buffers Extra: {pformat(buffers_known - buffers_seen)}"
|
|
86
|
+
)
|
|
87
|
+
except AssertionError as e:
|
|
88
|
+
errors.append(e)
|
|
89
|
+
|
|
90
|
+
assert len(errors) == 0, pformat(errors)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests the spatial ISL models.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import islpy as isl
|
|
8
|
+
|
|
9
|
+
from accelforge.frontend.mapping import MappingNode
|
|
10
|
+
from accelforge.model._looptree.reuse.isl.mapping_to_isl.types import (
|
|
11
|
+
Fill,
|
|
12
|
+
Occupancy,
|
|
13
|
+
SpatialTag,
|
|
14
|
+
TemporalTag,
|
|
15
|
+
)
|
|
16
|
+
from accelforge.model._looptree.reuse.isl.spatial import (
|
|
17
|
+
SimpleLinkTransferModel,
|
|
18
|
+
TransferInfo,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestSimpleLinkTransferModel(unittest.TestCase):
|
|
23
|
+
"""
|
|
24
|
+
Test the simple link transfer model. Adapted from the original test at the
|
|
25
|
+
following link:
|
|
26
|
+
https://github.com/NVlabs/timeloop/blob/master/src/unit-test/test-simple-link-transfer.cpp
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def test_simple_link_transfer_model_sandbox(self):
|
|
30
|
+
"""Independent sanity check of `SimpleLinkTransferModel`."""
|
|
31
|
+
buffer: MappingNode = MappingNode()
|
|
32
|
+
fill: Fill = Fill(
|
|
33
|
+
[TemporalTag(), SpatialTag(0, buffer), SpatialTag(1, buffer)], # type: ignore
|
|
34
|
+
isl.Map.read_from_str(
|
|
35
|
+
isl.DEFAULT_CONTEXT,
|
|
36
|
+
"{ spacetime[t, x, y] -> data[t+x+y] : 0 <= x < 2 and 0 <= y < 2 and 0 <= t < 2}",
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
occ: Occupancy = Occupancy(fill.tags, fill.map_)
|
|
40
|
+
link_transfer_model: SimpleLinkTransferModel = SimpleLinkTransferModel()
|
|
41
|
+
info: TransferInfo = link_transfer_model.apply(buffer, fill, occ)
|
|
42
|
+
|
|
43
|
+
assert info.fulfilled_fill.map_ == (
|
|
44
|
+
fulfilled_soln := isl.Map.read_from_str(
|
|
45
|
+
isl.DEFAULT_CONTEXT,
|
|
46
|
+
"{ spacetime[t = 1, x, y = 0] -> data[1 + x] : 0 <= x <= 1; "
|
|
47
|
+
" spacetime[t = 1, x = 0, y] -> data[1 + y] : 0 <= y <= 1 }",
|
|
48
|
+
)
|
|
49
|
+
), (
|
|
50
|
+
"`fulfilled_fill` and solution mismatch\n"
|
|
51
|
+
"--------------------------------------\n"
|
|
52
|
+
f"solution:\n{fulfilled_soln}\n"
|
|
53
|
+
f"received:\n{info.fulfilled_fill.map_}\n"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
assert info.unfulfilled_fill.map_ == (
|
|
57
|
+
unfulfilled_soln := isl.Map.read_from_str(
|
|
58
|
+
isl.DEFAULT_CONTEXT,
|
|
59
|
+
"{ spacetime[t = 0, x, y] -> data[x + y] : 0 <= x <= 1 and 0 <= y <= 1; "
|
|
60
|
+
" spacetime[t = 1, x = 1, y = 1] -> data[3] }",
|
|
61
|
+
)
|
|
62
|
+
), (
|
|
63
|
+
"`unfulfilled_fill` and solution mismatch\n"
|
|
64
|
+
"----------------------------------------\n"
|
|
65
|
+
f"solution:\n{unfulfilled_soln}\n"
|
|
66
|
+
f"received:\n{info.unfulfilled_fill.map_}\n"
|
|
67
|
+
)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests the temporal reuse analysis in ISL.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import islpy as isl
|
|
8
|
+
|
|
9
|
+
from accelforge.model._looptree.reuse.isl.mapping_to_isl.types import (
|
|
10
|
+
Occupancy,
|
|
11
|
+
SpatialTag,
|
|
12
|
+
TemporalTag,
|
|
13
|
+
)
|
|
14
|
+
from accelforge.model._looptree.reuse.isl.temporal import (
|
|
15
|
+
TemporalReuse,
|
|
16
|
+
analyze_temporal_reuse,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestTemporalReuseAnalysis(unittest.TestCase):
|
|
21
|
+
"""
|
|
22
|
+
Tests the temporal reuse analysis in ISL.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def test_multiple_loop_reuse_sandbox(self):
|
|
26
|
+
"""
|
|
27
|
+
Tests a very basic temporal reuse analysis case without needing the
|
|
28
|
+
`occupancies_from_mapping` function.
|
|
29
|
+
"""
|
|
30
|
+
# Loads in the CONV1D Config
|
|
31
|
+
occ: Occupancy = Occupancy(
|
|
32
|
+
[TemporalTag(), SpatialTag(0, None), TemporalTag()],
|
|
33
|
+
isl.Map.read_from_str(
|
|
34
|
+
isl.DEFAULT_CONTEXT,
|
|
35
|
+
(
|
|
36
|
+
"{ generic_iteration[t1, x, t0] -> tensor[d] : "
|
|
37
|
+
"t0 <= d < t0+3 and 0 <= t1 < 2 and 0 <= x < 2 and 0 <= t0 < 2 }"
|
|
38
|
+
),
|
|
39
|
+
).coalesce(),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
result: TemporalReuse = analyze_temporal_reuse(occ, True, True)
|
|
43
|
+
soln: isl.Map = isl.Map.read_from_str(
|
|
44
|
+
isl.DEFAULT_CONTEXT,
|
|
45
|
+
"{ generic_iteration[t1, x, t0] -> tensor[d] : "
|
|
46
|
+
"0 <= x < 2 and "
|
|
47
|
+
"(((t1 = 0) and (t0 = 0) and (0 <= d < 3)) or "
|
|
48
|
+
" ((t1 = 0) and (t0 = 1) and (d = 3)) or "
|
|
49
|
+
" ((t1 = 1) and (t0 = 0) and (d = 0)) or "
|
|
50
|
+
" ((t1 = 1) and (t0 = 1) and (d = 3))"
|
|
51
|
+
")}",
|
|
52
|
+
).coalesce()
|
|
53
|
+
fill: isl.Map = result.fill.map_
|
|
54
|
+
eff_occ: isl.Map = result.effective_occupancy.map_
|
|
55
|
+
print(eff_occ)
|
|
56
|
+
assert soln.is_equal(fill), f"Expected:\n{soln}\nReceived:\n{fill}"
|
tests/mapper/util.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions common to testing the isl mapper functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import islpy as isl
|
|
7
|
+
|
|
8
|
+
from ruamel.yaml import YAML
|
|
9
|
+
|
|
10
|
+
TEST_CONFIG_PATH: Path = Path(__file__).parent / "configs"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def to_isl_maps(obj: str | list | dict) -> dict:
|
|
14
|
+
"""
|
|
15
|
+
Given an object, attempt to reduce all strings in tree with isl.Map
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
obj:
|
|
20
|
+
A DAG which can be explored and contains isl.Map strings within it.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
`obj` but all strings are converted to isl.Map.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def _to_isl_maps(obj: str | dict | list) -> isl.Map | dict | list:
|
|
28
|
+
"""Recursively convert string ISL maps to isl.Map; leave others alone."""
|
|
29
|
+
if isinstance(obj, str):
|
|
30
|
+
return isl.Map.read_from_str(isl.DEFAULT_CONTEXT, obj)
|
|
31
|
+
if isinstance(obj, dict):
|
|
32
|
+
return {k: _to_isl_maps(v) for k, v in obj.items()}
|
|
33
|
+
if isinstance(obj, list):
|
|
34
|
+
return [_to_isl_maps(v) for v in obj]
|
|
35
|
+
return obj
|
|
36
|
+
|
|
37
|
+
return _to_isl_maps(obj) # type: ignore
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_solutions(path: Path) -> dict:
|
|
41
|
+
"""
|
|
42
|
+
Loads in a dictionary with the isl solutions to a workload problem.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
path:
|
|
47
|
+
The path to the solutions.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
A dictionary relating Python-based keys generated by the mapper (e.g.,
|
|
52
|
+
`BufferTensorEinsum` to their corresponding isl.Map.)
|
|
53
|
+
"""
|
|
54
|
+
# Load expected solutions (YAML file with string ISL maps)
|
|
55
|
+
yaml: YAML = YAML(typ="safe")
|
|
56
|
+
|
|
57
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
58
|
+
return to_isl_maps(yaml.load(f))
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
mapping:
|
|
2
|
+
nodes:
|
|
3
|
+
- !Storage
|
|
4
|
+
tensors: [T1, T0, W0]
|
|
5
|
+
component: MainMemory
|
|
6
|
+
- !Temporal
|
|
7
|
+
rank_variable: m
|
|
8
|
+
tile_shape: 128
|
|
9
|
+
- !Storage
|
|
10
|
+
tensors: [T1]
|
|
11
|
+
component: LocalBuffer
|
|
12
|
+
- !Temporal
|
|
13
|
+
rank_variable: n0
|
|
14
|
+
tile_shape: 1
|
|
15
|
+
- !Storage
|
|
16
|
+
tensors: [T0]
|
|
17
|
+
component: LocalBuffer
|
|
18
|
+
- !Temporal
|
|
19
|
+
rank_variable: n1
|
|
20
|
+
tile_shape: 1
|
|
21
|
+
- !Storage
|
|
22
|
+
tensors: [W0]
|
|
23
|
+
component: LocalBuffer
|
|
24
|
+
- !Temporal
|
|
25
|
+
rank_variable: m
|
|
26
|
+
tile_shape: 1
|
|
27
|
+
- !Compute
|
|
28
|
+
einsum: Matmul1
|
|
29
|
+
compute: MAC
|