offtarget 0.1.0__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.
- offload/__init__.py +10 -0
- offload/__main__.py +5 -0
- offload/_bundle.py +74 -0
- offload/_root/catalog/acc/claims.yaml +197 -0
- offload/_root/catalog/acc/clauses.yaml +391 -0
- offload/_root/catalog/acc/no_oracle.yaml +89 -0
- offload/_root/catalog/acc/out_of_scope.yaml +17 -0
- offload/_root/catalog/acc/rules.yaml +433 -0
- offload/_root/catalog/acc/semantic_atoms.yaml +27 -0
- offload/_root/catalog/acc/skeleton.yaml +1567 -0
- offload/_root/catalog/acc/spec_overrides.yaml +72 -0
- offload/_root/catalog/later_forms.yaml +76 -0
- offload/_root/catalog/machines.yaml +218 -0
- offload/_root/catalog/omp/claims.yaml +2047 -0
- offload/_root/catalog/omp/clauses.yaml +914 -0
- offload/_root/catalog/omp/derivations.yaml +177 -0
- offload/_root/catalog/omp/memory_modes.yaml +40 -0
- offload/_root/catalog/omp/no_oracle.yaml +373 -0
- offload/_root/catalog/omp/omp50_delta.yaml +377 -0
- offload/_root/catalog/omp/out_of_scope.yaml +64 -0
- offload/_root/catalog/omp/port_equivalence.yaml +352 -0
- offload/_root/catalog/omp/rules.yaml +3131 -0
- offload/_root/catalog/omp/rules_coverage.yaml +9939 -0
- offload/_root/catalog/omp/semantic_atoms.yaml +34 -0
- offload/_root/catalog/omp/skeleton.yaml +9181 -0
- offload/_root/catalog/omp/spec_overrides.yaml +932 -0
- offload/_root/catalog/toolchains.yaml +472 -0
- offload/_root/catalog/vendor_claims_generic.yaml +40925 -0
- offload/_root/data/canuse/b.json +1 -0
- offload/_root/data/canuse/c.json +1 -0
- offload/_root/data/canuse/columns.json +1 -0
- offload/_root/data/canuse/d.json +1 -0
- offload/_root/data/canuse/f.json +1 -0
- offload/_root/data/canuse/index.json +1 -0
- offload/_root/data/canuse/p.json +1 -0
- offload/_root/data/compilers/afar.json +1 -0
- offload/_root/data/compilers/cce19.json +1 -0
- offload/_root/data/compilers/cce20.json +1 -0
- offload/_root/data/compilers/cce21.json +1 -0
- offload/_root/data/compilers/cce21_4.json +1 -0
- offload/_root/data/compilers/gcc.json +1 -0
- offload/_root/data/compilers/gcc_sm80.json +1 -0
- offload/_root/data/compilers/nvhpc.json +1 -0
- offload/_root/data/compilers/nvhpc269.json +1 -0
- offload/_root/data/findings/AUTHORING.md +107 -0
- offload/_root/data/findings/README.md +33 -0
- offload/_root/data/findings/afar-c-error-directive-in-target-link.c +37 -0
- offload/_root/data/findings/afar-c-lastprivate-distribute-parallel-for-small-type.c +56 -0
- offload/_root/data/findings/afar-c-teams-distribute-reduction-first-team.c +59 -0
- offload/_root/data/findings/afar-c-update-iterator-copy-mode.c +45 -0
- offload/_root/data/findings/afar-c-xnack1-target-is-present.c +31 -0
- offload/_root/data/findings/afar-cce19-character-defaultmap.f90 +27 -0
- offload/_root/data/findings/afar-cce19-task-in-target-ice.f90 +23 -0
- offload/_root/data/findings/afar-clang-requires-device-safesync-hang.c +24 -0
- offload/_root/data/findings/afar-flang-firstprivate-map-two-targets.f90 +34 -0
- offload/_root/data/findings/afar-flang-loop-bind-teams-reduction.f90 +27 -0
- offload/_root/data/findings/afar-flang-task-reduction-max.f90 +31 -0
- offload/_root/data/findings/afar-flang-thread-limit-target-parallel-do.f90 +22 -0
- offload/_root/data/findings/afar-linear-ref-omp50.f90 +29 -0
- offload/_root/data/findings/afar-loop-bind-thread-in-teams.f90 +44 -0
- offload/_root/data/findings/afar-nontemporal-assumed-shape-ice.f90 +38 -0
- offload/_root/data/findings/afar-udr-derived-type-link.f90 +41 -0
- offload/_root/data/findings/afar-xnack1-atomic-min-nested-parallel.f90 +53 -0
- offload/_root/data/findings/afar-xnack1-present-not-enforced.f90 +36 -0
- offload/_root/data/findings/afar-xnack1-target-is-present.f90 +47 -0
- offload/_root/data/findings/apps/afar-cce-teams-private-array-nested-parallel-wrong.f90 +100 -0
- offload/_root/data/findings/apps/cce20-device-link-infer-address-spaces-crash.f90 +159 -0
- offload/_root/data/findings/apps/cce21-device-link-agpr-copy-mfma-assert.f90 +343 -0
- offload/_root/data/findings/apps/cce21-private-array-loaded-subscript-wrong.f90 +113 -0
- offload/_root/data/findings/apps/controls/bubble-simple-rddot.f90 +284 -0
- offload/_root/data/findings/apps/controls/bubble-two-substeps.f90 +287 -0
- offload/_root/data/findings/apps/controls/cbc-inline.f90 +97 -0
- offload/_root/data/findings/apps/controls/cbc-integers.f90 +91 -0
- offload/_root/data/findings/apps/controls/cbc-only-density.f90 +97 -0
- offload/_root/data/findings/apps/controls/cbc-only-velocity.f90 +97 -0
- offload/_root/data/findings/apps/controls/gcc-acc-c-tile-control.c +26 -0
- offload/_root/data/findings/apps/controls/gcc-acc-tile-control.f90 +29 -0
- offload/_root/data/findings/apps/controls/private-array-subscript-probes.f90 +45 -0
- offload/_root/data/findings/apps/controls/teams-private-array-read-par.f90 +31 -0
- offload/_root/data/findings/apps/controls/teams-private-array-seq.f90 +30 -0
- offload/_root/data/findings/apps/controls/teams-private-array-shared.f90 +34 -0
- offload/_root/data/findings/apps/controls/teams-private-array-split.f90 +36 -0
- offload/_root/data/findings/apps/controls/teams-private-array-write-par.f90 +31 -0
- offload/_root/data/findings/apps/gcc-acc-c-tile-partial-tiles-wrong.c +60 -0
- offload/_root/data/findings/apps/gcc-acc-tile-partial-tiles-wrong.f90 +64 -0
- offload/_root/data/findings/catalog/afar-c-complex-reduction-link.c +66 -0
- offload/_root/data/findings/catalog/afar-c-critical-hint-link.c +68 -0
- offload/_root/data/findings/catalog/afar-c-ordered-doacross-link.c +62 -0
- offload/_root/data/findings/catalog/afar-c-reduction-task-link.c +81 -0
- offload/_root/data/findings/catalog/afar-flang-absent-optional-target-crash.f90 +76 -0
- offload/_root/data/findings/catalog/afar-flang-critical-target-parallel-wrong.f90 +74 -0
- offload/_root/data/findings/catalog/afar-flang-dist-schedule-chunk.f90 +80 -0
- offload/_root/data/findings/catalog/afar-flang-linear-parallel-ice.f90 +68 -0
- offload/_root/data/findings/catalog/afar-flang-named-critical-link.f90 +67 -0
- offload/_root/data/findings/catalog/afar-flang-ordered-wrong.f90 +78 -0
- offload/_root/data/findings/catalog/afar-flang-reduction-minus-rejected.f90 +77 -0
- offload/_root/data/findings/catalog/afar-flang-reduction-task-ice.f90 +68 -0
- offload/_root/data/findings/catalog/afar-flang-sections-in-target-ice.f90 +67 -0
- offload/_root/data/findings/catalog/afar-flang-workdistribute-ice.f90 +71 -0
- offload/_root/data/findings/catalog/c-allocate-const-mem-firstprivate-wrong.c +79 -0
- offload/_root/data/findings/catalog/cce-acc-allocate-in-compute-crash.f90 +65 -0
- offload/_root/data/findings/catalog/cce-acc-character-dummy-routine-ice.f90 +81 -0
- offload/_root/data/findings/catalog/cce-acc-loop-seq-in-routine-wrong.f90 +81 -0
- offload/_root/data/findings/catalog/cce-acc-stop-in-compute-crash.f90 +62 -0
- offload/_root/data/findings/catalog/cce-allocators-stack-ice.f90 +81 -0
- offload/_root/data/findings/catalog/cce-atomic-default-mem-order-acquire-release-rejected.f90 +61 -0
- offload/_root/data/findings/catalog/cce-c-allocate-align-link.c +83 -0
- offload/_root/data/findings/catalog/cce-c-allocate-allocator-modifier-rejected.c +77 -0
- offload/_root/data/findings/catalog/cce-c-device-type-directive-name-ice.c +70 -0
- offload/_root/data/findings/catalog/cce-c-dist-schedule-chunk.c +81 -0
- offload/_root/data/findings/catalog/cce-c-f-pointer-device-link.f90 +70 -0
- offload/_root/data/findings/catalog/cce-c-lastprivate-parallel-in-seq-loop-wrong.c +64 -0
- offload/_root/data/findings/catalog/cce-c-long-double-ice.c +61 -0
- offload/_root/data/findings/catalog/cce-c-map-iterator-ice.c +92 -0
- offload/_root/data/findings/catalog/cce-c-motion-iterator-rejected.c +68 -0
- offload/_root/data/findings/catalog/cce-c-ordered-doacross-link.c +64 -0
- offload/_root/data/findings/catalog/cce-c-ordered-link.c +77 -0
- offload/_root/data/findings/catalog/cce-c-recursive-function-ice.c +62 -0
- offload/_root/data/findings/catalog/cce-c-reduction-inscan-ice.c +67 -0
- offload/_root/data/findings/catalog/cce-c-reduction-task-link.c +73 -0
- offload/_root/data/findings/catalog/cce-c-sections-in-target-wrong.c +70 -0
- offload/_root/data/findings/catalog/cce-c-single-masked-task-link.c +66 -0
- offload/_root/data/findings/catalog/cce-c-task-in-target-link.c +75 -0
- offload/_root/data/findings/catalog/cce-c-uses-allocators-traits-rejected.c +71 -0
- offload/_root/data/findings/catalog/cce-flang-allocate-const-mem-ice.f90 +67 -0
- offload/_root/data/findings/catalog/cce-flang-allocate-in-target-crash.f90 +68 -0
- offload/_root/data/findings/catalog/cce-flang-lastprivate-parallel-in-seq-loop-wrong.f90 +83 -0
- offload/_root/data/findings/catalog/cce-flang-stop-in-target-crash.f90 +64 -0
- offload/_root/data/findings/catalog/cce-iterator-link.f90 +67 -0
- offload/_root/data/findings/catalog/cce-linear-lastprivate-ice.f90 +69 -0
- offload/_root/data/findings/catalog/cce-nohost-link.f90 +90 -0
- offload/_root/data/findings/catalog/cce-reduction-inscan-ice.f90 +66 -0
- offload/_root/data/findings/catalog/cce-reduction-task-link.f90 +76 -0
- offload/_root/data/findings/catalog/cce19-reduction-task-addrspacecast-ice.f90 +77 -0
- offload/_root/data/findings/catalog/cce20-c-defaultmap-private-storage-rejected.c +85 -0
- offload/_root/data/findings/catalog/cce20-map-self-rejected.f90 +64 -0
- offload/_root/data/findings/catalog/cce21-c-declare-target-local-rejected.c +73 -0
- offload/_root/data/findings/catalog/cce21-c-target-loop-ice.c +77 -0
- offload/_root/data/findings/catalog/defaultmap-present-private-array-abort.f90 +73 -0
- offload/_root/data/findings/catalog/nvhpc-acc-associate-illegal-address.f90 +66 -0
- offload/_root/data/findings/catalog/nvhpc-c-function-pointer-kernel-missing.c +68 -0
- offload/_root/data/findings/catalog/nvhpc-c-long-double-kernel-missing.c +64 -0
- offload/_root/data/findings/catalog/nvhpc-c-static-local-kernel-missing.c +73 -0
- offload/_root/data/findings/catalog/nvhpc-c-vla-kernel-missing.c +63 -0
- offload/_root/data/findings/catalog/nvhpc-flang-type-bound-kernel-missing.f90 +86 -0
- offload/_root/data/findings/cce-acc-init-set-runtime-assert.f90 +35 -0
- offload/_root/data/findings/cce-acc-reduction-200-int8-scalars-wrong.f90 +1278 -0
- offload/_root/data/findings/cce-acc-routine-bind-module-ice.f90 +35 -0
- offload/_root/data/findings/cce-acc-self-condition-ignored.f90 +17 -0
- offload/_root/data/findings/cce-c-dist-schedule-segv.c +34 -0
- offload/_root/data/findings/cce-c-map-delete-refcount.c +47 -0
- offload/_root/data/findings/cce-c-map-present-assert.c +45 -0
- offload/_root/data/findings/cce-c-openmp45-device-link.c +34 -0
- offload/_root/data/findings/cce-c-parallel-for-in-target.c +73 -0
- offload/_root/data/findings/cce-defaultmap-tofrom-explicit-map.f90 +92 -0
- offload/_root/data/findings/cce-mapper-next-map-copy-back.f90 +48 -0
- offload/_root/data/findings/cce-trim-merge-output-one-character.f90 +40 -0
- offload/_root/data/findings/cce-uses-allocators-traits-omp50.f90 +28 -0
- offload/_root/data/findings/cce19-acc-if-false-link.f90 +17 -0
- offload/_root/data/findings/cce19-c-reduction-63-scalars-one-wrong.c +235 -0
- offload/_root/data/findings/cce19-target-parallel-guarded-loop.f90 +35 -0
- offload/_root/data/findings/cce19-target-parallel-single-ice.f90 +38 -0
- offload/_root/data/findings/cce21-alloc-2e32-sum-wrong.f90 +68 -0
- offload/_root/data/findings/cce21-defaultmap-aggregate-flag.f90 +52 -0
- offload/_root/data/findings/cce21-in-reduction-assumed-shape-write-lost.f90 +61 -0
- offload/_root/data/findings/cce21-in-reduction-taskwait-link.f90 +59 -0
- offload/_root/data/findings/cce21-linear-modifier-default-none.f90 +59 -0
- offload/_root/data/findings/clang-c-declare-target-to-omp52.c +50 -0
- offload/_root/data/findings/clang-c-linear-directive-name-hang.c +30 -0
- offload/_root/data/findings/clang-c-map-iterator-omp51.c +51 -0
- offload/_root/data/findings/clang-c-shared-declare-target-combined.c +58 -0
- offload/_root/data/findings/dataenv/cce-value-dummy-target-write-visible.f90 +74 -0
- offload/_root/data/findings/defaultmap-none-loop-variable.f90 +69 -0
- offload/_root/data/findings/fortran-loop-bind-thread-in-parallel.f90 +53 -0
- offload/_root/data/findings/fortran-schedule-static-in-target.f90 +55 -0
- offload/_root/data/findings/fresh/cce-common-block-name-in-map-rejected.f90 +47 -0
- offload/_root/data/findings/fresh/cce-if-stop-in-target-ice-one-condition.f90 +38 -0
- offload/_root/data/findings/fresh/cce-if-stop-in-target-ice.f90 +43 -0
- offload/_root/data/findings/fresh/cce-list-directed-print-in-target-copy-crash.f90 +40 -0
- offload/_root/data/findings/fresh/cce19-acc-automatic-array-copyout-copy-crash.f90 +56 -0
- offload/_root/data/findings/fresh/cce21-combined-if-runtime-expr-loop-skipped.f90 +57 -0
- offload/_root/data/findings/fresh/nvhpc-acc-gang-worker-collapse-nested-vector-reduction-lost.f90 +67 -0
- offload/_root/data/findings/fresh/nvhpc-teams-loop-module-allocatable-assign-fort2-crash.f90 +73 -0
- offload/_root/data/findings/fuzz/1131-afar.f90 +48 -0
- offload/_root/data/findings/fuzz/1391-cce20.f90 +40 -0
- offload/_root/data/findings/fuzz/14-cce20.f90 +36 -0
- offload/_root/data/findings/fuzz/1505-cce20.f90 +88 -0
- offload/_root/data/findings/fuzz/1540-afar.f90 +44 -0
- offload/_root/data/findings/fuzz/158-afar.f90 +63 -0
- offload/_root/data/findings/fuzz/16-cce20.f90 +39 -0
- offload/_root/data/findings/fuzz/1644-cce21.f90 +31 -0
- offload/_root/data/findings/fuzz/165-cce19.f90 +52 -0
- offload/_root/data/findings/fuzz/1749-cce20.f90 +34 -0
- offload/_root/data/findings/fuzz/1936-afar.f90 +61 -0
- offload/_root/data/findings/fuzz/1978-cce19.f90 +41 -0
- offload/_root/data/findings/fuzz/2014-cce19.f90 +46 -0
- offload/_root/data/findings/fuzz/2224-cce19.f90 +30 -0
- offload/_root/data/findings/fuzz/2334-cce19.f90 +57 -0
- offload/_root/data/findings/fuzz/536-cce19.f90 +38 -0
- offload/_root/data/findings/fuzz/591-cce19.f90 +54 -0
- offload/_root/data/findings/fuzz/650-afar.f90 +58 -0
- offload/_root/data/findings/fuzz/698-afar.f90 +68 -0
- offload/_root/data/findings/fuzz/700-afar.f90 +46 -0
- offload/_root/data/findings/fuzz/775-cce21.f90 +33 -0
- offload/_root/data/findings/fuzz/87-afar.f90 +47 -0
- offload/_root/data/findings/fuzz/916-afar.f90 +67 -0
- offload/_root/data/findings/fuzz/958-cce20.f90 +44 -0
- offload/_root/data/findings/fuzz/98-cce19.f90 +40 -0
- offload/_root/data/findings/fuzz/README.md +236 -0
- offload/_root/data/findings/fuzz/b1-121-afar.f90 +47 -0
- offload/_root/data/findings/fuzz/b1-183-afar.f90 +55 -0
- offload/_root/data/findings/fuzz/b1-22-cce20.f90 +38 -0
- offload/_root/data/findings/fuzz/b1-231-afar.f90 +56 -0
- offload/_root/data/findings/fuzz/b1-268-afar.f90 +46 -0
- offload/_root/data/findings/fuzz/b2-183-afar.f90 +57 -0
- offload/_root/data/findings/fuzz/b2-209-cce19.f90 +51 -0
- offload/_root/data/findings/fuzz/b2-213-afar.f90 +63 -0
- offload/_root/data/findings/fuzz/b2-52-afar.f90 +56 -0
- offload/_root/data/findings/fuzz/b2-68-afar.f90 +54 -0
- offload/_root/data/findings/fuzz/b2-85-cce20.f90 +55 -0
- offload/_root/data/findings/fuzz/b3-188-cce19.f90 +90 -0
- offload/_root/data/findings/fuzz/b3-190-cce21.f90 +88 -0
- offload/_root/data/findings/fuzz/b3-197-cce19.f90 +77 -0
- offload/_root/data/findings/fuzz/b3-250-cce20.f90 +89 -0
- offload/_root/data/findings/fuzz/b3-278-cce19.f90 +70 -0
- offload/_root/data/findings/fuzz/b3-45-cce21.f90 +83 -0
- offload/_root/data/findings/fuzz/b3-54-afar.f90 +67 -0
- offload/_root/data/findings/fuzz/b3-61-cce20.f90 +100 -0
- offload/_root/data/findings/fuzz/b3-9-afar.f90 +100 -0
- offload/_root/data/findings/fuzz/b3-9-cce21.f90 +103 -0
- offload/_root/data/findings/fuzz/b3-94-afar.f90 +80 -0
- offload/_root/data/findings/fuzz/b4-39-afar.f90 +141 -0
- offload/_root/data/findings/fuzz/b4-86-cce19.f90 +71 -0
- offload/_root/data/findings/fuzz/controls/gcc-complex-pointer-store-control.f90 +28 -0
- offload/_root/data/findings/fuzz/controls/gcc-declare-reduction-module-control.f90 +29 -0
- offload/_root/data/findings/fuzz/controls/gcc-target-simd-map-nontemporal-control.f90 +21 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-allocatable-component-mapped-control.f90 +22 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-allocatable-component-unreferenced-control.f90 +22 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-default-none-removed-control.f90 +18 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-default-shared-control.f90 +18 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-defaultmap-firstprivate-removed-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-defaultmap-to-scalar-reduction-mapped-control.f90 +17 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-defaultmap-to-scalar-removed-control.f90 +17 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-defaultmap-tofrom-lastprivate-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-depend-explicit-map-control.f90 +22 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-depend-removed-control.f90 +22 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-distribute-end-distribute-control.f90 +16 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-distribute-parallel-num-threads-removed-control.f90 +26 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-distribute-parallel-removed-control.f90 +22 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-distribute-simd-no-end-directive-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-explicit-length-character-dummy-control.f90 +18 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-loop-character-array-value-control.f90 +23 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-loop-character-distribute-control.f90 +20 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-map-always-first-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-map-always-removed-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-num-threads-removed-control.f90 +12 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-parallel-firstprivate-dropped-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-parallel-single-nowait-control.f90 +13 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-parallel-split-control.f90 +15 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-simd-collapse-split-control.f90 +21 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-simd-end-directive-control.f90 +14 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-simd-no-collapse-control.f90 +19 -0
- offload/_root/data/findings/fuzz/controls/nvhpc-target-simd-split-no-end-directive-control.f90 +15 -0
- offload/_root/data/findings/fuzz/gcc-declare-reduction-module-not-found.f90 +66 -0
- offload/_root/data/findings/fuzz/gcc-strided-target-update-rejected.f90 +58 -0
- offload/_root/data/findings/fuzz/gcc-target-simd-map-nontemporal-rejected.f90 +54 -0
- offload/_root/data/findings/fuzz/nvhpc-allocatable-component-implicit-map-illegal-address.f90 +84 -0
- offload/_root/data/findings/fuzz/nvhpc-assumed-length-character-dummy-map-ice.f90 +69 -0
- offload/_root/data/findings/fuzz/nvhpc-default-none-reduction-lastprivate-fort1-crash.f90 +70 -0
- offload/_root/data/findings/fuzz/nvhpc-defaultmap-firstprivate-lastprivate-ice.f90 +71 -0
- offload/_root/data/findings/fuzz/nvhpc-defaultmap-to-scalar-reduction-lost.f90 +82 -0
- offload/_root/data/findings/fuzz/nvhpc-depend-implicit-map-illegal-address.f90 +81 -0
- offload/_root/data/findings/fuzz/nvhpc-distribute-parallel-num-threads-writes-lost.f90 +79 -0
- offload/_root/data/findings/fuzz/nvhpc-end-distribute-simd-rejected.f90 +70 -0
- offload/_root/data/findings/fuzz/nvhpc-loop-character-achar-unsupported.f90 +75 -0
- offload/_root/data/findings/fuzz/nvhpc-map-always-after-map-to-not-copied-back.f90 +70 -0
- offload/_root/data/findings/fuzz/nvhpc-num-threads-reduction-identity-lost.f90 +54 -0
- offload/_root/data/findings/fuzz/nvhpc-target-parallel-firstprivate-translate-failure.f90 +66 -0
- offload/_root/data/findings/fuzz/nvhpc-target-parallel-single-hang.f90 +68 -0
- offload/_root/data/findings/fuzz/nvhpc-target-simd-collapse-translate-failure.f90 +73 -0
- offload/_root/data/findings/fuzz/nvhpc-target-simd-no-end-directive-rejected.f90 +68 -0
- offload/_root/data/findings/fuzz/par-s1-2082-gcc_g90.f90 +71 -0
- offload/_root/data/findings/fuzz/s1-2370-cce21.f90 +67 -0
- offload/_root/data/findings/fuzz/s1-2592-cce21.f90 +56 -0
- offload/_root/data/findings/fuzz/s1-3463-cce21.f90 +92 -0
- offload/_root/data/findings/fuzz/s1-4339-afar.f90 +79 -0
- offload/_root/data/findings/fuzz/s1-6085-cce21.f90 +96 -0
- offload/_root/data/findings/fuzz/s1-6760-cce20.f90 +65 -0
- offload/_root/data/findings/fuzz/s1-6888-cce21.f90 +76 -0
- offload/_root/data/findings/fuzz/s1-7882-cce20.f90 +63 -0
- offload/_root/data/findings/fuzz/s1-8634-cce21.f90 +45 -0
- offload/_root/data/findings/fuzz/s1-91-cce21.f90 +92 -0
- offload/_root/data/findings/fuzz/s1-9443-afar.f90 +59 -0
- offload/_root/data/findings/fuzz/s1-9914-cce19.f90 +78 -0
- offload/_root/data/findings/gcc/controls/gcc-acc-c-detach-control.c +34 -0
- offload/_root/data/findings/gcc/controls/gcc-acc-detach-control.f90 +26 -0
- offload/_root/data/findings/gcc/controls/gcc-defaultmap-to-pointer-control.f90 +31 -0
- offload/_root/data/findings/gcc/controls/gcc-target-in-task-control.c +26 -0
- offload/_root/data/findings/gcc/controls/gcc-target-in-task-control.f90 +21 -0
- offload/_root/data/findings/gcc/gcc-acc-bind-device-type-rejected.f90 +71 -0
- offload/_root/data/findings/gcc/gcc-acc-c-bind-device-type-rejected.c +76 -0
- offload/_root/data/findings/gcc/gcc-acc-c-detach-delete-attach-underflow.c +74 -0
- offload/_root/data/findings/gcc/gcc-acc-c-gang-dim-rejected.c +79 -0
- offload/_root/data/findings/gcc/gcc-acc-c-link-in-routine-rejected.c +82 -0
- offload/_root/data/findings/gcc/gcc-acc-detach-delete-attach-underflow.f90 +66 -0
- offload/_root/data/findings/gcc/gcc-acc-gang-dim-collapse-force-rejected.f90 +69 -0
- offload/_root/data/findings/gcc/gcc-acc-init-set-shutdown-rejected.f90 +70 -0
- offload/_root/data/findings/gcc/gcc-acc-link-in-routine-rejected.f90 +82 -0
- offload/_root/data/findings/gcc/gcc-acc-use-device-allocatable-rejected.f90 +88 -0
- offload/_root/data/findings/gcc/gcc-c-motion-mapper-rejected.c +110 -0
- offload/_root/data/findings/gcc/gcc-c-omp60-undocumented-rejected.c +76 -0
- offload/_root/data/findings/gcc/gcc-c-omp60-unimplemented-rejected.c +119 -0
- offload/_root/data/findings/gcc/gcc-c-target-in-task-mandatory-device-not-found.c +87 -0
- offload/_root/data/findings/gcc/gcc-c-uses-allocators-traits-unimplemented.c +85 -0
- offload/_root/data/findings/gcc/gcc-declare-mapper-rejected.f90 +85 -0
- offload/_root/data/findings/gcc/gcc-defaultmap-to-pointer-copy-back.f90 +66 -0
- offload/_root/data/findings/gcc/gcc-loop-bind-default-none-rejected.f90 +93 -0
- offload/_root/data/findings/gcc/gcc-omp60-undocumented-rejected.f90 +72 -0
- offload/_root/data/findings/gcc/gcc-omp60-unimplemented-rejected.f90 +112 -0
- offload/_root/data/findings/gcc/gcc-target-in-task-mandatory-device-not-found.f90 +83 -0
- offload/_root/data/findings/gcc/gcc-uses-allocators-traits-unimplemented.f90 +78 -0
- offload/_root/data/findings/harvest/afar-flang-strided-target-update.f90 +96 -0
- offload/_root/data/findings/harvest/cce-acc-declare-create-module-allocatable-xnack1-fault.f90 +58 -0
- offload/_root/data/findings/harvest/cce-c-implicit-struct-map-partly-present.c +100 -0
- offload/_root/data/findings/harvest/cce-c-strided-target-update.c +74 -0
- offload/_root/data/findings/harvest/cce-ftn-target-parallel-thread-query-ice.f90 +67 -0
- offload/_root/data/findings/harvest/cce-named-constant-array-declare-target-routine-rejected.f90 +69 -0
- offload/_root/data/findings/harvest/cce-use-device-ptr-c-ptr-not-converted.f90 +64 -0
- offload/_root/data/findings/harvest/cce21-declare-target-link-module-variable-write-lost.f90 +63 -0
- offload/_root/data/findings/harvest/cce21-internal-procedure-calls-internal-in-target-fault.f90 +71 -0
- offload/_root/data/findings/harvest/controls/cce-c-implicit-struct-map-partly-present-target-only-control.c +22 -0
- offload/_root/data/findings/harvest/controls/cce-c-implicit-struct-map-partly-present-whole-control.c +23 -0
- offload/_root/data/findings/harvest/controls/gcc-acc-declare-create-allocatable-control.f90 +34 -0
- offload/_root/data/findings/harvest/controls/gcc-c-same-item-two-maps-control.c +17 -0
- offload/_root/data/findings/harvest/controls/gcc-c-target-data-struct-pointer-section-control.c +27 -0
- offload/_root/data/findings/harvest/controls/gcc-c-target-data-two-maps-control.c +20 -0
- offload/_root/data/findings/harvest/controls/gcc-same-item-two-maps-control.f90 +16 -0
- offload/_root/data/findings/harvest/controls/gcc-teams-simd-matmul-allocatable-control.f90 +27 -0
- offload/_root/data/findings/harvest/gcc-acc-declare-create-allocatable-not-mapped.f90 +66 -0
- offload/_root/data/findings/harvest/gcc-c-same-item-two-maps-rejected.c +45 -0
- offload/_root/data/findings/harvest/gcc-c-strided-section-rejected.c +70 -0
- offload/_root/data/findings/harvest/gcc-c-target-data-struct-pointer-section-ice.c +78 -0
- offload/_root/data/findings/harvest/gcc-c-target-data-two-maps-ice.c +49 -0
- offload/_root/data/findings/harvest/gcc-same-item-two-maps-rejected.f90 +46 -0
- offload/_root/data/findings/harvest/gcc-teams-simd-matmul-allocatable-ice.f90 +53 -0
- offload/_root/data/findings/harvest/nvhpc-c-target-data-if-false-use-device-ptr-garbage.c +49 -0
- offload/_root/data/findings/harvest/nvhpc-named-constant-array-declare-target-routine-rejected.f90 +65 -0
- offload/_root/data/findings/harvest/nvhpc-use-device-ptr-c-ptr-not-found.f90 +60 -0
- offload/_root/data/findings/harvest/nvhpc2511-target-nowait-in-parallel-for-ice.c +59 -0
- offload/_root/data/findings/hecbench/controls/f16-ctl-float-array.c +28 -0
- offload/_root/data/findings/hecbench/controls/pc-ctl-builtin-popcount.c +37 -0
- offload/_root/data/findings/hecbench/controls/pc-ctl-shift-sum.c +43 -0
- offload/_root/data/findings/hecbench/gcc-c-float16-array-in-target-lto-ice.c +65 -0
- offload/_root/data/findings/hecbench/gcc-c-swar-popcount-assembler-error.c +80 -0
- offload/_root/data/findings/index.yaml +2453 -0
- offload/_root/data/findings/malloc/afar-device-malloc-in-kernel-corrupts-records.c +371 -0
- offload/_root/data/findings/malloc/controls/afar-first-use-malloc-direct.c +52 -0
- offload/_root/data/findings/malloc/controls/afar-first-use-malloc-fence.c +57 -0
- offload/_root/data/findings/malloc/controls/afar-first-use-malloc-flush.c +57 -0
- offload/_root/data/findings/malloc/controls/afar-first-use-malloc-stack.c +52 -0
- offload/_root/data/findings/multithread-allocatable-section-maps.f90 +91 -0
- offload/_root/data/findings/nested/afar-cce-c-call-result-member-in-target-rejected.c +69 -0
- offload/_root/data/findings/nested/afar-cce-c-update-struct-and-member-rejected.c +92 -0
- offload/_root/data/findings/nested/afar-flang-pointer-root-allocatable-component-enter-data-fault.f90 +121 -0
- offload/_root/data/findings/nested/cce-c-struct-and-nested-pointee-sections-ice.c +79 -0
- offload/_root/data/findings/nested/cce-fortran-nested-allocatable-component-copy-fault.f90 +64 -0
- offload/_root/data/findings/nested/cce-fortran-pointer-to-type-with-allocatable-scalar-component-typed-transfer.f90 +93 -0
- offload/_root/data/findings/nested/cce-fortran-update-to-pointer-root-allocatable-scalar-component-no-accelerator-object.f90 +80 -0
- offload/_root/data/findings/nested/controls/c3-ctl-nested-data.c +27 -0
- offload/_root/data/findings/nested/controls/c5-acc-serial-struct-and-array.c +26 -0
- offload/_root/data/findings/nested/controls/e2-ctl-two-directives.c +42 -0
- offload/_root/data/findings/nested/controls/e3-ctl-attach-clause.c +42 -0
- offload/_root/data/findings/nested/controls/f3-pointer-array-only.c +33 -0
- offload/_root/data/findings/nested/controls/f5-ctl-copyout-exit.c +33 -0
- offload/_root/data/findings/nested/controls/f6-ctl-pointer-to-struct-array.c +28 -0
- offload/_root/data/findings/nested/controls/g2-ctl-allocatable.f90 +34 -0
- offload/_root/data/findings/nested/controls/g2-ctl-entered-to.f90 +34 -0
- offload/_root/data/findings/nested/controls/g3-ctl-from-struct-no-element.c +27 -0
- offload/_root/data/findings/nested/controls/g3-ptrs-two-elements-to.c +27 -0
- offload/_root/data/findings/nested/controls/g3-ptrs-two-elements-tofrom.c +27 -0
- offload/_root/data/findings/nested/controls/g5-ctl-element-pointers-only.f90 +36 -0
- offload/_root/data/findings/nested/controls/g5-ctl-root-pointer-only.f90 +36 -0
- offload/_root/data/findings/nested/controls/gp2-ctl-no-mapper-explicit-maps.c +24 -0
- offload/_root/data/findings/nested/controls/gt2-ctl-no-always.c +26 -0
- offload/_root/data/findings/nested/controls/gt3-ctl-always-on-structure-only.c +26 -0
- offload/_root/data/findings/nested/controls/j1-embedded-struct-pointer-to-struct.c +24 -0
- offload/_root/data/findings/nested/controls/j2-ctl-pointer-instead-of-embedded.c +24 -0
- offload/_root/data/findings/nested/controls/j6-ctl-struct-and-one-pointee-level.c +23 -0
- offload/_root/data/findings/nested/controls/j7-ctl-struct-and-embedded-pointee.c +24 -0
- offload/_root/data/findings/nested/controls/m2-ctl-variable-root.f90 +32 -0
- offload/_root/data/findings/nested/controls/m3-ctl-fixed-array-component.f90 +32 -0
- offload/_root/data/findings/nested/controls/m5-ctl-no-enter-data.f90 +33 -0
- offload/_root/data/findings/nested/controls/n8-ctl-fixed-array-in-component.f90 +33 -0
- offload/_root/data/findings/nested/controls/n9-ctl-allocatable-in-the-variable.f90 +33 -0
- offload/_root/data/findings/nested/controls/ns4-ctl-two-directives-struct-then-pointee.c +27 -0
- offload/_root/data/findings/nested/controls/ns8-ctl-enter-together-exit-split.c +26 -0
- offload/_root/data/findings/nested/controls/nu3-ctl-update-pointee-only.c +28 -0
- offload/_root/data/findings/nested/controls/p2-ctl-pointer-variable.c +27 -0
- offload/_root/data/findings/nested/controls/p3-ctl-direct-member.c +26 -0
- offload/_root/data/findings/nested/controls/q2-ctl-fixed-array.f90 +37 -0
- offload/_root/data/findings/nested/controls/q3-ctl-allocatable-component-of-the-variable.f90 +38 -0
- offload/_root/data/findings/nested/controls/ta2-ctl-no-allocatable-component.f90 +42 -0
- offload/_root/data/findings/nested/controls/ta3-ctl-allocatable-scalar-in-the-variable.f90 +38 -0
- offload/_root/data/findings/nested/controls/ta4-ctl-pointer-component-only.f90 +42 -0
- offload/_root/data/findings/nested/controls/u3-ctl-update-member-only.c +24 -0
- offload/_root/data/findings/nested/controls/u4-ctl-two-updates.c +25 -0
- offload/_root/data/findings/nested/controls/u5-ctl-same-list-in-map.c +25 -0
- offload/_root/data/findings/nested/controls/ua2-ctl-variable-root.f90 +37 -0
- offload/_root/data/findings/nested/controls/ua4-ctl-to-in-place-of-alloc-and-update.f90 +37 -0
- offload/_root/data/findings/nested/controls/v2-ctl-parent-first.c +25 -0
- offload/_root/data/findings/nested/controls/v4-ctl-embedded-member.c +24 -0
- offload/_root/data/findings/nested/gcc-acc-c-exit-data-of-a-pointer-array-element-target-hangs.c +83 -0
- offload/_root/data/findings/nested/gcc-acc-c-parent-and-shared-pointee-one-directive.c +88 -0
- offload/_root/data/findings/nested/gcc-acc-c-struct-and-member-array-one-directive.c +84 -0
- offload/_root/data/findings/nested/gcc-c-always-on-pointer-member-section-ice.c +75 -0
- offload/_root/data/findings/nested/gcc-c-declare-mapper-pointer-member-section-gpu-fault.c +93 -0
- offload/_root/data/findings/nested/gcc-c-from-struct-and-pointee-section-rejected.c +83 -0
- offload/_root/data/findings/nested/gcc-fortran-pointer-component-alloc-bounds-lost.f90 +62 -0
- offload/_root/data/findings/nested/gcc-fortran-root-and-element-pointer-components-ice.f90 +77 -0
- offload/_root/data/findings/nested/nvhpc-c-pointee-before-parent-in-one-map-list-copy-fault.c +55 -0
- offload/_root/data/findings/nested/nvhpc-c-update-from-structure-overwrites-attached-pointer-segv.c +86 -0
- offload/_root/data/findings/nvhpc-acc-atomic-update-sum-fort2-crash.f90 +53 -0
- offload/_root/data/findings/nvhpc-c-acc-atomic-update-sum-ice.c +43 -0
- offload/_root/data/findings/nvhpc-c-dist-schedule-chunk-compile-hang.c +41 -0
- offload/_root/data/findings/nvhpc-c-map-present-ignored.c +42 -0
- offload/_root/data/findings/nvhpc-c-ordered-in-target-nvcpfe-crash.c +92 -0
- offload/_root/data/findings/nvhpc-c-parallel-for-firstprivate-in-target.c +62 -0
- offload/_root/data/findings/nvhpc-c-parallel-if-in-target-nvvm-ice.c +56 -0
- offload/_root/data/findings/nvhpc-defaultmap-firstprivate-explicit-map.f90 +45 -0
- offload/_root/data/findings/nvhpc-defaultmap-from-allocatable-indexing.f90 +60 -0
- offload/_root/data/findings/nvhpc-depend-inoutset-ignored.f90 +64 -0
- offload/_root/data/findings/nvhpc-dist-schedule-chunk-illegal-address.f90 +52 -0
- offload/_root/data/findings/nvhpc-managed-acc-shutdown-host-access.f90 +42 -0
- offload/_root/data/findings/nvhpc-parallel-if-in-target-nvvm-ice.f90 +60 -0
- offload/_root/data/findings/oop/afar-final-dealloc-device-link.f90 +85 -0
- offload/_root/data/findings/oop/afar-pdt-length-parameter-not-implemented.f90 +65 -0
- offload/_root/data/findings/oop/cce-class-is-device-link.f90 +86 -0
- offload/_root/data/findings/oop/cce-copy-alloc-component-section-fault.f90 +73 -0
- offload/_root/data/findings/oop/cce-copy-parent-to-component-tofrom-lost.f90 +65 -0
- offload/_root/data/findings/oop/cce-copy-second-member-section-lost.f90 +65 -0
- offload/_root/data/findings/oop/cce-element-component-map-lost.f90 +64 -0
- offload/_root/data/findings/oop/cce-final-dealloc-device-abort.f90 +85 -0
- offload/_root/data/findings/oop/cce-pdt-default-mapper-rejected.f90 +71 -0
- offload/_root/data/findings/oop/cce-polymorphic-dispatch-device-link.f90 +100 -0
- offload/_root/data/findings/oop/cce-section-of-element-component-overlap.f90 +76 -0
- offload/_root/data/findings/oop/cce-select-type-guard-not-taken.f90 +91 -0
- offload/_root/data/findings/oop/cce-udr-derived-type-unsupported.f90 +69 -0
- offload/_root/data/findings/oop/cce21-element-component-map-lost.f90 +62 -0
- offload/_root/data/findings/oop/controls/alloccomp-comp-only.f90 +44 -0
- offload/_root/data/findings/oop/controls/alloccomp-whole-explicit-component.f90 +50 -0
- offload/_root/data/findings/oop/controls/alloccomp-whole.f90 +49 -0
- offload/_root/data/findings/oop/controls/elemsec-element.f90 +47 -0
- offload/_root/data/findings/oop/controls/final-local.f90 +64 -0
- offload/_root/data/findings/oop/controls/host-class-star-select-type.f90 +58 -0
- offload/_root/data/findings/oop/controls/host-firstprivate-defined-assignment.f90 +54 -0
- offload/_root/data/findings/oop/controls/host-lastprivate-defined-assignment.f90 +58 -0
- offload/_root/data/findings/oop/controls/host-private-finalization.f90 +51 -0
- offload/_root/data/findings/oop/controls/host-select-type.f90 +65 -0
- offload/_root/data/findings/oop/controls/parent-and-comp-component-only.f90 +45 -0
- offload/_root/data/findings/oop/controls/pdt-kind.f90 +46 -0
- offload/_root/data/findings/oop/controls/pdt-len-host.f90 +43 -0
- offload/_root/data/findings/oop/controls/pdt-len-unparameterized.f90 +46 -0
- offload/_root/data/findings/oop/controls/poly-dispatch-static.f90 +75 -0
- offload/_root/data/findings/oop/controls/section-alloc-whole-component.f90 +49 -0
- offload/_root/data/findings/oop/controls/section-element-whole-array.f90 +50 -0
- offload/_root/data/findings/oop/controls/section-element-whole-component.f90 +50 -0
- offload/_root/data/findings/oop/controls/section-fixed.f90 +43 -0
- offload/_root/data/findings/oop/controls/tbp-override.f90 +64 -0
- offload/_root/data/findings/oop/gcc-acc-parent-and-member-data-rejected.f90 +63 -0
- offload/_root/data/findings/oop/gcc-pdt-length-parameter-abort.f90 +68 -0
- offload/_root/data/findings/oop/gcc-polymorphic-dispatch-abort.f90 +97 -0
- offload/_root/data/findings/oop/gcc-vtab-not-marked-for-offload.f90 +94 -0
- offload/_root/data/findings/oop/nvhpc-copy-alloc-component-illegal-address.f90 +76 -0
- offload/_root/data/findings/oop/nvhpc-copy-pdt-length-parameter-illegal-address.f90 +69 -0
- offload/_root/data/findings/oop/nvhpc-named-mapper-rejected.f90 +65 -0
- offload/_root/data/findings/oop/nvhpc-polymorphic-dispatch-translate-failure.f90 +90 -0
- offload/_root/data/findings/oop/nvhpc-polymorphism-runtime-unsupported.f90 +94 -0
- offload/_root/data/findings/oop/nvhpc-type-bound-call-rejected.f90 +89 -0
- offload/_root/data/findings/oop/nvhpc-udr-derived-type-rejected.f90 +67 -0
- offload/_root/data/findings/reviews/afar-c-error-directive-in-target-link.json +217 -0
- offload/_root/data/findings/reviews/afar-c-lastprivate-distribute-parallel-for-small-type.json +113 -0
- offload/_root/data/findings/reviews/afar-c-teams-distribute-reduction-first-team.json +130 -0
- offload/_root/data/findings/reviews/afar-c-update-iterator-copy-mode.json +113 -0
- offload/_root/data/findings/reviews/afar-cce19-character-defaultmap.json +292 -0
- offload/_root/data/findings/reviews/afar-clang-requires-device-safesync-hang.json +191 -0
- offload/_root/data/findings/reviews/afar-flang-firstprivate-map-two-targets.json +130 -0
- offload/_root/data/findings/reviews/afar-flang-loop-bind-teams-reduction.json +126 -0
- offload/_root/data/findings/reviews/afar-flang-task-reduction-max.json +113 -0
- offload/_root/data/findings/reviews/afar-flang-thread-limit-target-parallel-do.json +113 -0
- offload/_root/data/findings/reviews/afar-loop-bind-thread-in-teams.json +191 -0
- offload/_root/data/findings/reviews/afar-nontemporal-assumed-shape-ice.json +113 -0
- offload/_root/data/findings/reviews/afar-udr-derived-type-link.json +113 -0
- offload/_root/data/findings/reviews/afar-xnack1-atomic-min-nested-parallel.json +113 -0
- offload/_root/data/findings/reviews/afar-xnack1-target-is-present.json +113 -0
- offload/_root/data/findings/reviews/apps--afar-cce-teams-private-array-nested-parallel-wrong.json +113 -0
- offload/_root/data/findings/reviews/apps--cce20-device-link-infer-address-spaces-crash.json +113 -0
- offload/_root/data/findings/reviews/apps--cce21-device-link-agpr-copy-mfma-assert.json +113 -0
- offload/_root/data/findings/reviews/apps--cce21-private-array-loaded-subscript-wrong.json +113 -0
- offload/_root/data/findings/reviews/apps--gcc-acc-c-tile-partial-tiles-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-c-ordered-doacross-link.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-c-reduction-task-link.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-absent-optional-target-crash.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-critical-target-parallel-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-dist-schedule-chunk.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-linear-parallel-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-named-critical-link.json +126 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-ordered-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-reduction-minus-rejected.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-sections-in-target-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--afar-flang-workdistribute-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--c-allocate-const-mem-firstprivate-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-acc-character-dummy-routine-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-acc-loop-seq-in-routine-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-allocators-stack-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-c-allocate-align-link.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-c-allocate-allocator-modifier-rejected.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-c-dist-schedule-chunk.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-c-f-pointer-device-link.json +130 -0
- offload/_root/data/findings/reviews/catalog--cce-c-long-double-ice.json +217 -0
- offload/_root/data/findings/reviews/catalog--cce-c-map-iterator-ice.json +217 -0
- offload/_root/data/findings/reviews/catalog--cce-c-recursive-function-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-c-sections-in-target-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-flang-allocate-in-target-crash.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-flang-lastprivate-parallel-in-seq-loop-wrong.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-flang-stop-in-target-crash.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-iterator-link.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-linear-lastprivate-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-reduction-inscan-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce-reduction-task-link.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce19-reduction-task-addrspacecast-ice.json +113 -0
- offload/_root/data/findings/reviews/catalog--cce20-c-defaultmap-private-storage-rejected.json +217 -0
- offload/_root/data/findings/reviews/catalog--cce20-map-self-rejected.json +204 -0
- offload/_root/data/findings/reviews/catalog--cce21-c-target-loop-ice.json +126 -0
- offload/_root/data/findings/reviews/catalog--defaultmap-present-private-array-abort.json +236 -0
- offload/_root/data/findings/reviews/catalog--nvhpc-acc-associate-illegal-address.json +113 -0
- offload/_root/data/findings/reviews/catalog--nvhpc-c-function-pointer-kernel-missing.json +268 -0
- offload/_root/data/findings/reviews/cce-acc-init-set-runtime-assert.json +113 -0
- offload/_root/data/findings/reviews/cce-acc-reduction-200-int8-scalars-wrong.json +113 -0
- offload/_root/data/findings/reviews/cce-acc-routine-bind-module-ice.json +113 -0
- offload/_root/data/findings/reviews/cce-c-dist-schedule-segv.json +113 -0
- offload/_root/data/findings/reviews/cce-c-map-delete-refcount.json +149 -0
- offload/_root/data/findings/reviews/cce-c-map-present-assert.json +126 -0
- offload/_root/data/findings/reviews/cce-c-openmp45-device-link.json +113 -0
- offload/_root/data/findings/reviews/cce-c-parallel-for-in-target.json +141 -0
- offload/_root/data/findings/reviews/cce-mapper-next-map-copy-back.json +208 -0
- offload/_root/data/findings/reviews/cce-uses-allocators-traits-omp50.json +191 -0
- offload/_root/data/findings/reviews/cce19-c-reduction-63-scalars-one-wrong.json +113 -0
- offload/_root/data/findings/reviews/cce19-target-parallel-guarded-loop.json +113 -0
- offload/_root/data/findings/reviews/cce19-target-parallel-single-ice.json +113 -0
- offload/_root/data/findings/reviews/cce21-alloc-2e32-sum-wrong.json +113 -0
- offload/_root/data/findings/reviews/cce21-defaultmap-aggregate-flag.json +210 -0
- offload/_root/data/findings/reviews/cce21-in-reduction-assumed-shape-write-lost.json +113 -0
- offload/_root/data/findings/reviews/cce21-in-reduction-taskwait-link.json +113 -0
- offload/_root/data/findings/reviews/clang-c-declare-target-to-omp52.json +113 -0
- offload/_root/data/findings/reviews/clang-c-linear-directive-name-hang.json +113 -0
- offload/_root/data/findings/reviews/clang-c-shared-declare-target-combined.json +132 -0
- offload/_root/data/findings/reviews/dataenv--cce-value-dummy-target-write-visible.json +113 -0
- offload/_root/data/findings/reviews/defaultmap-none-loop-variable.json +113 -0
- offload/_root/data/findings/reviews/fortran-schedule-static-in-target.json +113 -0
- offload/_root/data/findings/reviews/fresh--cce-common-block-name-in-map-rejected.json +113 -0
- offload/_root/data/findings/reviews/fresh--cce-list-directed-print-in-target-copy-crash.json +217 -0
- offload/_root/data/findings/reviews/fresh--cce19-acc-automatic-array-copyout-copy-crash.json +113 -0
- offload/_root/data/findings/reviews/fresh--cce21-combined-if-runtime-expr-loop-skipped.json +113 -0
- offload/_root/data/findings/reviews/fresh--nvhpc-acc-gang-worker-collapse-nested-vector-reduction-lost.json +113 -0
- offload/_root/data/findings/reviews/fresh--nvhpc-teams-loop-module-allocatable-assign-fort2-crash.json +113 -0
- offload/_root/data/findings/reviews/fuzz--1505-cce20.json +113 -0
- offload/_root/data/findings/reviews/fuzz--1540-afar.json +113 -0
- offload/_root/data/findings/reviews/fuzz--1978-cce19.json +130 -0
- offload/_root/data/findings/reviews/fuzz--2334-cce19.json +113 -0
- offload/_root/data/findings/reviews/fuzz--591-cce19.json +147 -0
- offload/_root/data/findings/reviews/fuzz--650-afar.json +113 -0
- offload/_root/data/findings/reviews/fuzz--916-afar.json +130 -0
- offload/_root/data/findings/reviews/fuzz--98-cce19.json +113 -0
- offload/_root/data/findings/reviews/fuzz--b1-121-afar.json +160 -0
- offload/_root/data/findings/reviews/fuzz--b2-209-cce19.json +141 -0
- offload/_root/data/findings/reviews/fuzz--b2-68-afar.json +113 -0
- offload/_root/data/findings/reviews/fuzz--b2-85-cce20.json +217 -0
- offload/_root/data/findings/reviews/fuzz--b3-188-cce19.json +113 -0
- offload/_root/data/findings/reviews/fuzz--b3-278-cce19.json +212 -0
- offload/_root/data/findings/reviews/fuzz--b3-54-afar.json +113 -0
- offload/_root/data/findings/reviews/fuzz--b3-61-cce20.json +191 -0
- offload/_root/data/findings/reviews/fuzz--b4-86-cce19.json +113 -0
- offload/_root/data/findings/reviews/fuzz--gcc-declare-reduction-module-not-found.json +113 -0
- offload/_root/data/findings/reviews/fuzz--gcc-target-simd-map-nontemporal-rejected.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-allocatable-component-implicit-map-illegal-address.json +141 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-assumed-length-character-dummy-map-ice.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-default-none-reduction-lastprivate-fort1-crash.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-defaultmap-firstprivate-lastprivate-ice.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-defaultmap-to-scalar-reduction-lost.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-depend-implicit-map-illegal-address.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-distribute-parallel-num-threads-writes-lost.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-end-distribute-simd-rejected.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-loop-character-achar-unsupported.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-map-always-after-map-to-not-copied-back.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-num-threads-reduction-identity-lost.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-target-parallel-firstprivate-translate-failure.json +191 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-target-parallel-single-hang.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-target-simd-collapse-translate-failure.json +113 -0
- offload/_root/data/findings/reviews/fuzz--nvhpc-target-simd-no-end-directive-rejected.json +113 -0
- offload/_root/data/findings/reviews/fuzz--par-s1-2082-gcc_g90.json +126 -0
- offload/_root/data/findings/reviews/fuzz--s1-2370-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-2592-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-3463-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-6760-cce20.json +130 -0
- offload/_root/data/findings/reviews/fuzz--s1-6888-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-7882-cce20.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-8634-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-91-cce21.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-9443-afar.json +113 -0
- offload/_root/data/findings/reviews/fuzz--s1-9914-cce19.json +141 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-bind-device-type-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-detach-delete-attach-underflow.json +314 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-gang-dim-collapse-force-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-init-set-shutdown-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-link-in-routine-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-acc-use-device-allocatable-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-c-motion-mapper-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-c-omp60-undocumented-rejected.json +217 -0
- offload/_root/data/findings/reviews/gcc--gcc-c-omp60-unimplemented-rejected.json +236 -0
- offload/_root/data/findings/reviews/gcc--gcc-c-target-in-task-mandatory-device-not-found.json +236 -0
- offload/_root/data/findings/reviews/gcc--gcc-c-uses-allocators-traits-unimplemented.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-declare-mapper-rejected.json +113 -0
- offload/_root/data/findings/reviews/gcc--gcc-defaultmap-to-pointer-copy-back.json +217 -0
- offload/_root/data/findings/reviews/gcc--gcc-loop-bind-default-none-rejected.json +113 -0
- offload/_root/data/findings/reviews/harvest--afar-flang-strided-target-update.json +141 -0
- offload/_root/data/findings/reviews/harvest--cce-acc-declare-create-module-allocatable-xnack1-fault.json +113 -0
- offload/_root/data/findings/reviews/harvest--cce-c-implicit-struct-map-partly-present.json +217 -0
- offload/_root/data/findings/reviews/harvest--cce-c-strided-target-update.json +141 -0
- offload/_root/data/findings/reviews/harvest--cce-ftn-target-parallel-thread-query-ice.json +130 -0
- offload/_root/data/findings/reviews/harvest--cce-named-constant-array-declare-target-routine-rejected.json +113 -0
- offload/_root/data/findings/reviews/harvest--cce-use-device-ptr-c-ptr-not-converted.json +113 -0
- offload/_root/data/findings/reviews/harvest--cce21-declare-target-link-module-variable-write-lost.json +113 -0
- offload/_root/data/findings/reviews/harvest--cce21-internal-procedure-calls-internal-in-target-fault.json +158 -0
- offload/_root/data/findings/reviews/harvest--gcc-acc-declare-create-allocatable-not-mapped.json +204 -0
- offload/_root/data/findings/reviews/harvest--gcc-c-same-item-two-maps-rejected.json +143 -0
- offload/_root/data/findings/reviews/harvest--gcc-c-strided-section-rejected.json +164 -0
- offload/_root/data/findings/reviews/harvest--gcc-c-target-data-struct-pointer-section-ice.json +113 -0
- offload/_root/data/findings/reviews/harvest--gcc-c-target-data-two-maps-ice.json +113 -0
- offload/_root/data/findings/reviews/harvest--gcc-teams-simd-matmul-allocatable-ice.json +113 -0
- offload/_root/data/findings/reviews/harvest--nvhpc-c-target-data-if-false-use-device-ptr-garbage.json +113 -0
- offload/_root/data/findings/reviews/harvest--nvhpc-named-constant-array-declare-target-routine-rejected.json +126 -0
- offload/_root/data/findings/reviews/harvest--nvhpc-use-device-ptr-c-ptr-not-found.json +113 -0
- offload/_root/data/findings/reviews/harvest--nvhpc2511-target-nowait-in-parallel-for-ice.json +130 -0
- offload/_root/data/findings/reviews/hecbench--gcc-c-float16-array-in-target-lto-ice.json +217 -0
- offload/_root/data/findings/reviews/hecbench--gcc-c-swar-popcount-assembler-error.json +126 -0
- offload/_root/data/findings/reviews/malloc--afar-device-malloc-in-kernel-corrupts-records.json +270 -0
- offload/_root/data/findings/reviews/multithread-allocatable-section-maps.json +191 -0
- offload/_root/data/findings/reviews/nested--afar-cce-c-call-result-member-in-target-rejected.json +113 -0
- offload/_root/data/findings/reviews/nested--afar-cce-c-update-struct-and-member-rejected.json +126 -0
- offload/_root/data/findings/reviews/nested--afar-flang-pointer-root-allocatable-component-enter-data-fault.json +191 -0
- offload/_root/data/findings/reviews/nested--cce-c-struct-and-nested-pointee-sections-ice.json +113 -0
- offload/_root/data/findings/reviews/nested--cce-fortran-nested-allocatable-component-copy-fault.json +214 -0
- offload/_root/data/findings/reviews/nested--cce-fortran-pointer-to-type-with-allocatable-scalar-component-typed-transfer.json +191 -0
- offload/_root/data/findings/reviews/nested--cce-fortran-update-to-pointer-root-allocatable-scalar-component-no-accelerator-object.json +297 -0
- offload/_root/data/findings/reviews/nested--gcc-acc-c-exit-data-of-a-pointer-array-element-target-hangs.json +204 -0
- offload/_root/data/findings/reviews/nested--gcc-acc-c-parent-and-shared-pointee-one-directive.json +130 -0
- offload/_root/data/findings/reviews/nested--gcc-acc-c-struct-and-member-array-one-directive.json +141 -0
- offload/_root/data/findings/reviews/nested--gcc-c-always-on-pointer-member-section-ice.json +113 -0
- offload/_root/data/findings/reviews/nested--gcc-c-declare-mapper-pointer-member-section-gpu-fault.json +113 -0
- offload/_root/data/findings/reviews/nested--gcc-c-from-struct-and-pointee-section-rejected.json +113 -0
- offload/_root/data/findings/reviews/nested--gcc-fortran-pointer-component-alloc-bounds-lost.json +217 -0
- offload/_root/data/findings/reviews/nested--gcc-fortran-root-and-element-pointer-components-ice.json +217 -0
- offload/_root/data/findings/reviews/nested--nvhpc-c-pointee-before-parent-in-one-map-list-copy-fault.json +204 -0
- offload/_root/data/findings/reviews/nested--nvhpc-c-update-from-structure-overwrites-attached-pointer-segv.json +191 -0
- offload/_root/data/findings/reviews/nvhpc-c-acc-atomic-update-sum-ice.json +277 -0
- offload/_root/data/findings/reviews/nvhpc-c-dist-schedule-chunk-compile-hang.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-c-map-present-ignored.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-c-ordered-in-target-nvcpfe-crash.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-c-parallel-for-firstprivate-in-target.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-defaultmap-firstprivate-explicit-map.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-defaultmap-from-allocatable-indexing.json +132 -0
- offload/_root/data/findings/reviews/nvhpc-depend-inoutset-ignored.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-dist-schedule-chunk-illegal-address.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-managed-acc-shutdown-host-access.json +113 -0
- offload/_root/data/findings/reviews/nvhpc-parallel-if-in-target-nvvm-ice.json +113 -0
- offload/_root/data/findings/reviews/oop--afar-final-dealloc-device-link.json +132 -0
- offload/_root/data/findings/reviews/oop--afar-pdt-length-parameter-not-implemented.json +113 -0
- offload/_root/data/findings/reviews/oop--cce-class-is-device-link.json +130 -0
- offload/_root/data/findings/reviews/oop--cce-copy-alloc-component-section-fault.json +217 -0
- offload/_root/data/findings/reviews/oop--cce-copy-parent-to-component-tofrom-lost.json +217 -0
- offload/_root/data/findings/reviews/oop--cce-copy-second-member-section-lost.json +113 -0
- offload/_root/data/findings/reviews/oop--cce-element-component-map-lost.json +113 -0
- offload/_root/data/findings/reviews/oop--cce-final-dealloc-device-abort.json +208 -0
- offload/_root/data/findings/reviews/oop--cce-pdt-default-mapper-rejected.json +191 -0
- offload/_root/data/findings/reviews/oop--cce-polymorphic-dispatch-device-link.json +247 -0
- offload/_root/data/findings/reviews/oop--cce-section-of-element-component-overlap.json +113 -0
- offload/_root/data/findings/reviews/oop--cce-select-type-guard-not-taken.json +191 -0
- offload/_root/data/findings/reviews/oop--cce-udr-derived-type-unsupported.json +132 -0
- offload/_root/data/findings/reviews/oop--gcc-acc-parent-and-member-data-rejected.json +141 -0
- offload/_root/data/findings/reviews/oop--gcc-pdt-length-parameter-abort.json +141 -0
- offload/_root/data/findings/reviews/oop--gcc-polymorphic-dispatch-abort.json +217 -0
- offload/_root/data/findings/reviews/oop--gcc-vtab-not-marked-for-offload.json +113 -0
- offload/_root/data/findings/reviews/oop--nvhpc-copy-alloc-component-illegal-address.json +113 -0
- offload/_root/data/findings/reviews/oop--nvhpc-copy-pdt-length-parameter-illegal-address.json +236 -0
- offload/_root/data/findings/reviews/oop--nvhpc-named-mapper-rejected.json +113 -0
- offload/_root/data/findings/reviews/oop--nvhpc-polymorphic-dispatch-translate-failure.json +223 -0
- offload/_root/data/findings/reviews/oop--nvhpc-polymorphism-runtime-unsupported.json +126 -0
- offload/_root/data/findings/reviews/oop--nvhpc-type-bound-call-rejected.json +113 -0
- offload/_root/data/findings/reviews/oop--nvhpc-udr-derived-type-rejected.json +113 -0
- offload/_root/data/findings/reviews/stress--afar-c-lastprivate-combined-target-not-mapped.json +113 -0
- offload/_root/data/findings/reviews/stress--afar-target-scalar-implicit-firstprivate.json +175 -0
- offload/_root/data/findings/reviews/stress--cce-acc-declare-create-scalar-serial-firstprivate.json +113 -0
- offload/_root/data/findings/reviews/stress--cce-c-distribute-lastprivate-lost.json +113 -0
- offload/_root/data/findings/reviews/stress--cce-c-flto-offload-dropped.json +204 -0
- offload/_root/data/findings/reviews/stress--cce-ftn-cif-record-split-abort.json +113 -0
- offload/_root/data/findings/reviews/stress--cce-lastprivate-num-threads-collapse-simd.json +113 -0
- offload/_root/data/findings/reviews/stress--cce-teams-reduction-many-teams-wrap.json +113 -0
- offload/_root/data/findings/reviews/stress--cce21-declare-target-scalar-map-write-lost.json +113 -0
- offload/_root/data/findings/reviews/stress--gcc-declare-target-allocatable-component-ice.json +191 -0
- offload/_root/data/findings/reviews/stress--nvhpc-acc-derived-type-component-not-copied.json +126 -0
- offload/_root/data/findings/reviews/stress--nvhpc-c-lastprivate-teams-distribute-parallel-for-lost.json +113 -0
- offload/_root/data/findings/reviews/stress--nvhpc-declare-target-scalar-write-lost.json +113 -0
- offload/_root/data/findings/reviews/stress--nvhpc-lastprivate-combined-target-not-mapped.json +113 -0
- offload/_root/data/findings/reviews/stress--nvhpc-target-scalar-implicit-firstprivate.json +130 -0
- offload/_root/data/findings/reviews/target-update-sections-in-parallel.json +113 -0
- offload/_root/data/findings/stress/afar-c-lastprivate-combined-target-not-mapped.c +72 -0
- offload/_root/data/findings/stress/afar-target-scalar-implicit-firstprivate.f90 +47 -0
- offload/_root/data/findings/stress/cce-acc-declare-create-scalar-serial-firstprivate.f90 +43 -0
- offload/_root/data/findings/stress/cce-c-distribute-lastprivate-lost.c +52 -0
- offload/_root/data/findings/stress/cce-c-flto-offload-dropped.c +73 -0
- offload/_root/data/findings/stress/cce-ftn-cif-record-split-abort.f90 +109 -0
- offload/_root/data/findings/stress/cce-lastprivate-num-threads-collapse-simd.f90 +66 -0
- offload/_root/data/findings/stress/cce-teams-reduction-many-teams-wrap.f90 +55 -0
- offload/_root/data/findings/stress/cce21-declare-target-scalar-map-write-lost.f90 +58 -0
- offload/_root/data/findings/stress/controls/gcc-declare-target-allocatable-component-control.f90 +29 -0
- offload/_root/data/findings/stress/gcc-declare-target-allocatable-component-ice.f90 +61 -0
- offload/_root/data/findings/stress/nvhpc-acc-derived-type-component-not-copied.f90 +33 -0
- offload/_root/data/findings/stress/nvhpc-c-lastprivate-teams-distribute-parallel-for-lost.c +62 -0
- offload/_root/data/findings/stress/nvhpc-declare-target-scalar-write-lost.f90 +43 -0
- offload/_root/data/findings/stress/nvhpc-lastprivate-combined-target-not-mapped.f90 +60 -0
- offload/_root/data/findings/stress/nvhpc-target-scalar-implicit-firstprivate.f90 +41 -0
- offload/_root/data/findings/target-update-sections-in-parallel.f90 +53 -0
- offload/_root/data/issues.json +1 -0
- offload/_root/data/search.json +1 -0
- offload/_root/data/vendor/checks/build.py +288 -0
- offload/_version.py +24 -0
- offload/canuse.py +88 -0
- offload/cli.py +52 -0
- offload/data.py +85 -0
- offload/engine/__init__.py +0 -0
- offload/engine/acc_c_gen.py +415 -0
- offload/engine/acc_gen.py +1104 -0
- offload/engine/acc_rules.py +656 -0
- offload/engine/apps.py +804 -0
- offload/engine/baseline.py +324 -0
- offload/engine/c_gen.py +883 -0
- offload/engine/c_program.py +913 -0
- offload/engine/c_rules.py +503 -0
- offload/engine/campaign.py +1180 -0
- offload/engine/campaigns/__init__.py +2 -0
- offload/engine/campaigns/hecbench.py +153 -0
- offload/engine/campaigns/nested.py +76 -0
- offload/engine/campaigns/oop.py +61 -0
- offload/engine/canary.py +275 -0
- offload/engine/catalog.py +860 -0
- offload/engine/citations.py +532 -0
- offload/engine/clang_oracle.py +208 -0
- offload/engine/combos.py +234 -0
- offload/engine/confirm/__init__.py +2 -0
- offload/engine/confirm/backlog.py +159 -0
- offload/engine/confirm/claims.py +423 -0
- offload/engine/confirm/collectors.py +665 -0
- offload/engine/confirm/decisions.py +202 -0
- offload/engine/confirm/draft.py +195 -0
- offload/engine/confirm/engine.py +157 -0
- offload/engine/confirm/execute.py +382 -0
- offload/engine/confirm/facts.py +467 -0
- offload/engine/confirm/findings.py +617 -0
- offload/engine/confirm/forms.py +145 -0
- offload/engine/confirm/ingest.py +372 -0
- offload/engine/confirm/jobs.py +215 -0
- offload/engine/confirm/legality.py +323 -0
- offload/engine/confirm/machines.py +254 -0
- offload/engine/confirm/minimize.py +268 -0
- offload/engine/confirm/model.py +249 -0
- offload/engine/confirm/ports.py +107 -0
- offload/engine/confirm/programs.py +222 -0
- offload/engine/confirm/registry.py +151 -0
- offload/engine/confirm/regress.py +278 -0
- offload/engine/confirm/rules.py +565 -0
- offload/engine/confirm/store.py +63 -0
- offload/engine/confirm/triage.py +838 -0
- offload/engine/confirm/validate.py +607 -0
- offload/engine/confirm/witness.py +355 -0
- offload/engine/corpus_check.py +388 -0
- offload/engine/coverage.py +318 -0
- offload/engine/dataenv_gen.py +1318 -0
- offload/engine/dataenv_rules.py +278 -0
- offload/engine/devtemps.py +146 -0
- offload/engine/expected.py +2559 -0
- offload/engine/f2c.py +1783 -0
- offload/engine/finding_claims.py +330 -0
- offload/engine/finding_header.py +229 -0
- offload/engine/finding_rows.py +382 -0
- offload/engine/flang_oracle.py +299 -0
- offload/engine/fsource.py +620 -0
- offload/engine/fuzz.py +2455 -0
- offload/engine/fuzz_base.py +2016 -0
- offload/engine/fuzz_campaign.py +592 -0
- offload/engine/fuzz_exec.py +798 -0
- offload/engine/fuzz_min.py +1049 -0
- offload/engine/fuzz_profile.py +340 -0
- offload/engine/fuzz_report.py +1270 -0
- offload/engine/fuzz_steer.py +181 -0
- offload/engine/gate.py +1013 -0
- offload/engine/gate_report.py +711 -0
- offload/engine/gate_run.py +118 -0
- offload/engine/gate_stored.py +466 -0
- offload/engine/gen.py +1114 -0
- offload/engine/gen_templates.py +2583 -0
- offload/engine/grammar.py +695 -0
- offload/engine/harness.py +1472 -0
- offload/engine/harvest/__init__.py +3 -0
- offload/engine/harvest/c_runtime.py +465 -0
- offload/engine/harvest/checks.py +534 -0
- offload/engine/harvest/convert.py +784 -0
- offload/engine/harvest/f_runtime.py +668 -0
- offload/engine/harvest/filters.py +338 -0
- offload/engine/harvest/history.py +122 -0
- offload/engine/harvest/inventory.py +399 -0
- offload/engine/harvest2/__init__.py +5 -0
- offload/engine/harvest2/aomp.py +119 -0
- offload/engine/harvest2/examples.py +116 -0
- offload/engine/harvest2/gomp.py +679 -0
- offload/engine/harvest2/hand.py +150 -0
- offload/engine/harvest2/split.py +78 -0
- offload/engine/harvest_known/__init__.py +2 -0
- offload/engine/harvest_known/apps.py +65 -0
- offload/engine/harvest_known/cases.py +128 -0
- offload/engine/harvest_known/centres.py +184 -0
- offload/engine/harvest_known/forum.py +180 -0
- offload/engine/harvest_known/relnotes.py +42 -0
- offload/engine/harvest_known/textscan.py +107 -0
- offload/engine/hdrwrap.py +42 -0
- offload/engine/hecbench.py +568 -0
- offload/engine/hecbench_report.py +265 -0
- offload/engine/hecbench_run.py +483 -0
- offload/engine/idioms.py +1427 -0
- offload/engine/kbody_cites.py +81 -0
- offload/engine/kbody_emit.py +949 -0
- offload/engine/kbody_gen.py +795 -0
- offload/engine/legality_review.py +236 -0
- offload/engine/localcfg.py +58 -0
- offload/engine/malloc_dd.py +267 -0
- offload/engine/mutate.py +1933 -0
- offload/engine/nested_cites.py +196 -0
- offload/engine/nested_emit.py +789 -0
- offload/engine/nested_gen.py +1721 -0
- offload/engine/offload_scope.py +197 -0
- offload/engine/ompvv.py +624 -0
- offload/engine/oop_gen.py +2249 -0
- offload/engine/prerun.py +1435 -0
- offload/engine/program_source.py +739 -0
- offload/engine/provenance.py +103 -0
- offload/engine/reduce.py +2098 -0
- offload/engine/report.py +3374 -0
- offload/engine/root.py +33 -0
- offload/engine/rules.py +4256 -0
- offload/engine/run_matrix.py +325 -0
- offload/engine/site/__init__.py +1 -0
- offload/engine/site/columns.py +53 -0
- offload/engine/site/data.py +648 -0
- offload/engine/site/header.py +228 -0
- offload/engine/site/inputs.py +115 -0
- offload/engine/site/matrix.py +434 -0
- offload/engine/site/scrub.py +294 -0
- offload/engine/skeleton.py +121 -0
- offload/engine/spec_text.py +242 -0
- offload/engine/stress.py +4122 -0
- offload/engine/stress_c.py +1000 -0
- offload/engine/stress_exec.py +805 -0
- offload/engine/stress_min.py +248 -0
- offload/engine/stress_report.py +552 -0
- offload/engine/textclean.py +97 -0
- offload/engine/toolchains.py +1070 -0
- offload/engine/transforms.py +511 -0
- offload/engine/usage.py +1252 -0
- offload/engine/widen.py +673 -0
- offload/engine/widen_progs.py +2396 -0
- offload/issues.py +146 -0
- offtarget-0.1.0.dist-info/METADATA +86 -0
- offtarget-0.1.0.dist-info/RECORD +886 -0
- offtarget-0.1.0.dist-info/WHEEL +4 -0
- offtarget-0.1.0.dist-info/entry_points.txt +2 -0
- offtarget-0.1.0.dist-info/licenses/LICENSE +21 -0
- offtarget-0.1.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +20 -0
offload/engine/stress.py
ADDED
|
@@ -0,0 +1,4122 @@
|
|
|
1
|
+
"""Stress programs: very large and very complex device-offload programs that
|
|
2
|
+
are still legal and still checked.
|
|
3
|
+
|
|
4
|
+
A stress program is a list of kernels. Each is its own subroutine in a kernel
|
|
5
|
+
module with its own data and prints its own value, so a wrong answer names the
|
|
6
|
+
kernel. Values come from a Python model (``Kernel.value``). The program prints
|
|
7
|
+
``K <name> <value>`` per kernel and ends with the fuzz line
|
|
8
|
+
``RESULT checksum=<sum mod P> ran_on_host=<0|1>`` (``offload.engine.fuzz_exec``).
|
|
9
|
+
``AXES`` lists the axes and ``build(axis, size, seed, ...)`` makes a program:
|
|
10
|
+
many kernels, deep nests and call chains, long clause lists, continuation
|
|
11
|
+
lines and names, derived types, many translation units, async sequences and
|
|
12
|
+
kernel shapes taken from real failing codes (``template``).
|
|
13
|
+
Each program is labelled ``legal``, ``illegal_probe`` (beyond a base-language
|
|
14
|
+
limit, so a rejection is right), ``unspecified`` or ``impl_defined``;
|
|
15
|
+
``limits`` relabels a program that exceeds a base-language limit."""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import random
|
|
19
|
+
import re
|
|
20
|
+
from dataclasses import dataclass, field
|
|
21
|
+
|
|
22
|
+
P = 2147483629 # checksum modulus (offload.engine.fuzz)
|
|
23
|
+
LINE_MAX = 132 # F2008 3.3.2.1 / F2018 6.3.2.1
|
|
24
|
+
CONT_MAX = 255 # F2008 3.3.2.4 / F2018 6.3.2.4
|
|
25
|
+
NAME_MAX = 63 # F2008 3.2.2 / F2018 6.2.2
|
|
26
|
+
BOUND = 2 ** 62
|
|
27
|
+
FILE_MARK = "!@file " # offload.engine.fuzz_base bundle marker
|
|
28
|
+
WIDTH = 100 # default packing width of long lines
|
|
29
|
+
|
|
30
|
+
CITES = {
|
|
31
|
+
"line": "Fortran 2018 6.3.2.1: a free-form line shall contain at most "
|
|
32
|
+
"132 characters",
|
|
33
|
+
"cont": "Fortran 2018 6.3.2.4: a free-form statement shall not have "
|
|
34
|
+
"more than 255 continuation lines",
|
|
35
|
+
"name": "Fortran 2018 6.2.2: a name shall have at most 63 characters",
|
|
36
|
+
"xtu": "OpenMP 5.2 §13.8 p.284 (a procedure referenced in a target "
|
|
37
|
+
"construct is treated as if named in an enter clause) and §5.8.4 "
|
|
38
|
+
"p.158 (a device version is created when the enter clause is in "
|
|
39
|
+
"the compilation unit of the definition), §1.2.2 p.3 (for "
|
|
40
|
+
"Fortran a compilation unit is a program unit; OpenACC 3.4 "
|
|
41
|
+
"§2.15.1 p.91 likewise): a procedure of another module needs its "
|
|
42
|
+
"own declare target / routine directive, even in the same file",
|
|
43
|
+
"tbp": "OpenMP 5.0 §1.2.6 p.15 / 5.2 §1.2.6 p.18 (mappable type): all "
|
|
44
|
+
"type-bound procedures accessed in a target region must appear "
|
|
45
|
+
"in a declare target directive",
|
|
46
|
+
"poly": "an OpenMP 6.0 program: 6.0 §7.9.6 p.287, if a map list item "
|
|
47
|
+
"has polymorphic type, the behavior is unspecified (5.2 restricts "
|
|
48
|
+
"polymorphic allocatables only in firstprivate, lastprivate and "
|
|
49
|
+
"copyprivate, §5.4.4, §5.4.5, §5.7.2 p.146; it does not make "
|
|
50
|
+
"this map unspecified, so the program declares 6.0)",
|
|
51
|
+
"contig": "OpenMP 5.2 §5.8.3 p.155: a map list item that is an array "
|
|
52
|
+
"section must specify contiguous storage",
|
|
53
|
+
"stride": "OpenMP 5.2 §5.9 p.164: data-motion clause list items may "
|
|
54
|
+
"include array sections with stride expressions",
|
|
55
|
+
"share": "OpenMP 5.2 §5.8.3 p.155: two map list items on one construct "
|
|
56
|
+
"must not share original storage unless one contains the other",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class Overflow(Exception):
|
|
61
|
+
"""A model value left the bound: the kernel is redrawn smaller."""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def chk(v: int) -> int:
|
|
65
|
+
if abs(v) >= BOUND:
|
|
66
|
+
raise Overflow(v)
|
|
67
|
+
return v
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def fmod(a: int, p: int) -> int:
|
|
71
|
+
"""Fortran MOD (sign of the dividend)."""
|
|
72
|
+
r = abs(a) % abs(p)
|
|
73
|
+
return r if a >= 0 else -r
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def cksum(vals) -> int:
|
|
77
|
+
"""The Fortran helper ``st_cksum``: sum of mod(v_i, P)*(mod(i,7)+1),
|
|
78
|
+
i from 1, mod P (every v_i >= 0)."""
|
|
79
|
+
cs = 0
|
|
80
|
+
for i, v in enumerate(vals, 1):
|
|
81
|
+
cs = (cs + fmod(v, P) * (i % 7 + 1)) % P
|
|
82
|
+
return cs
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# --- text helpers -----------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
def pack(head: str, atoms: list[str], indent: str, sentinel: str | None,
|
|
88
|
+
width: int = WIDTH) -> list[str]:
|
|
89
|
+
"""Lines of a statement (sentinel None) or directive (``!$omp``)
|
|
90
|
+
made of `head` and `atoms`, wrapped with ``&`` continuations at
|
|
91
|
+
`width` columns (an atom is never split; an atom wider than the line
|
|
92
|
+
gets a line of its own)."""
|
|
93
|
+
lead = f"{indent}{sentinel} " if sentinel else indent
|
|
94
|
+
cont = f"{indent}{sentinel}& " if sentinel else f"{indent} & "
|
|
95
|
+
lines, cur = [], lead + head
|
|
96
|
+
for a in atoms:
|
|
97
|
+
if len(cur) + len(a) + 1 + 2 > width and cur.strip() not in (
|
|
98
|
+
lead.strip(), cont.strip()):
|
|
99
|
+
lines.append(cur + " &")
|
|
100
|
+
cur = cont + a
|
|
101
|
+
else:
|
|
102
|
+
cur = cur + ("" if cur.endswith(("(", " ")) or a.startswith(
|
|
103
|
+
(")", ",")) else " ") + a
|
|
104
|
+
lines.append(cur)
|
|
105
|
+
return lines
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def list_atoms(name: str, items: list[str], mod: str = "") -> list[str]:
|
|
109
|
+
"""Atoms of a clause with a list: ``name(mod: a,`` ``b,`` ... ``z)``."""
|
|
110
|
+
if not items:
|
|
111
|
+
return []
|
|
112
|
+
head = f"{name}({mod}: " if mod else f"{name}("
|
|
113
|
+
out = []
|
|
114
|
+
for k, it in enumerate(items):
|
|
115
|
+
piece = it + ("," if k < len(items) - 1 else ")")
|
|
116
|
+
out.append(head + piece if k == 0 else piece)
|
|
117
|
+
return out
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def call_lines(indent: str, name: str, args: list[str],
|
|
121
|
+
width: int = WIDTH) -> list[str]:
|
|
122
|
+
if not args:
|
|
123
|
+
return [f"{indent}call {name}()"]
|
|
124
|
+
return pack(f"call {name}(", [a + ("," if k < len(args) - 1 else ")")
|
|
125
|
+
for k, a in enumerate(args)],
|
|
126
|
+
indent, None, width)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def sum_lines(indent: str, target: str, terms: list[str],
|
|
130
|
+
width: int = WIDTH, chunk: int = 40) -> list[str]:
|
|
131
|
+
"""``target = target + t1 + t2 ...`` in statements of at most `chunk`
|
|
132
|
+
terms (a long expression is the exprs axis' business)."""
|
|
133
|
+
out = []
|
|
134
|
+
for k in range(0, len(terms), chunk):
|
|
135
|
+
part = terms[k:k + chunk]
|
|
136
|
+
out += pack(f"{target} = {target} +",
|
|
137
|
+
[t + (" +" if j < len(part) - 1 else "")
|
|
138
|
+
for j, t in enumerate(part)], indent, None, width)
|
|
139
|
+
return out
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def vname(prefix: str, k: int, width: int = 4) -> str:
|
|
143
|
+
return f"{prefix}{k:0{width}d}"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# --- directives for both models ------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
@dataclass
|
|
149
|
+
class Opts:
|
|
150
|
+
model: str = "omp" # omp | acc
|
|
151
|
+
spell: int = 50 # OpenMP spelling: 50 (5.0 forms) or 52
|
|
152
|
+
level: str = "f2018"
|
|
153
|
+
width: int = WIDTH
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def sent(self) -> str:
|
|
157
|
+
return "!$omp" if self.model == "omp" else "!$acc"
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# OpenMP chains (5.0 spellings; each a combined or split nest whose last
|
|
161
|
+
# leaf is a loop construct) and their OpenACC counterparts
|
|
162
|
+
OMP_CHAINS = (
|
|
163
|
+
("target teams distribute parallel do",),
|
|
164
|
+
("target teams distribute parallel do simd",),
|
|
165
|
+
("target parallel do",),
|
|
166
|
+
("target teams distribute",),
|
|
167
|
+
("target teams distribute simd",),
|
|
168
|
+
("target parallel do simd",),
|
|
169
|
+
("target simd",),
|
|
170
|
+
("target teams loop",),
|
|
171
|
+
("target", "teams distribute parallel do"),
|
|
172
|
+
("target teams", "distribute parallel do"),
|
|
173
|
+
("target", "parallel do"),
|
|
174
|
+
("target", "teams", "distribute parallel do"),
|
|
175
|
+
)
|
|
176
|
+
ACC_CHAINS = (
|
|
177
|
+
("parallel loop gang vector",),
|
|
178
|
+
("parallel loop",),
|
|
179
|
+
("kernels loop",),
|
|
180
|
+
("serial loop",),
|
|
181
|
+
("parallel", "loop gang vector"),
|
|
182
|
+
("kernels", "loop independent"),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def data_clauses(o: Opts, data: list[tuple[str, str]]) -> list[str]:
|
|
187
|
+
"""Atoms of the data clauses: [(item, to|from|tofrom|alloc)]."""
|
|
188
|
+
groups: dict[str, list[str]] = {}
|
|
189
|
+
for item, kind in data:
|
|
190
|
+
groups.setdefault(kind, []).append(item)
|
|
191
|
+
out = []
|
|
192
|
+
for kind in ("to", "from", "tofrom", "alloc"):
|
|
193
|
+
if kind not in groups:
|
|
194
|
+
continue
|
|
195
|
+
if o.model == "omp":
|
|
196
|
+
out += list_atoms("map", groups[kind], kind)
|
|
197
|
+
else:
|
|
198
|
+
name = {"to": "copyin", "from": "copyout", "tofrom": "copy",
|
|
199
|
+
"alloc": "create"}[kind]
|
|
200
|
+
out += list_atoms(name, groups[kind])
|
|
201
|
+
return out
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def region(o: Opts, chain: tuple, indent: str, data=(), private=(),
|
|
205
|
+
firstprivate=(), reduction=(), collapse: int = 0,
|
|
206
|
+
extra=(), loop_extra=()) -> tuple[list[str], list[str], str]:
|
|
207
|
+
"""(opening lines, closing lines, inner indent) of a loop region of
|
|
208
|
+
`chain` (a tuple of directive texts, outermost first): data clauses on
|
|
209
|
+
the first directive, privatization / reduction / collapse on the last
|
|
210
|
+
(the loop directive), `extra` atoms on the first, `loop_extra` on the
|
|
211
|
+
last. Fortran OpenMP: every directive gets its end directive (a
|
|
212
|
+
combined loop construct's is optional; written for symmetry)."""
|
|
213
|
+
opens, closes = [], []
|
|
214
|
+
ind = indent
|
|
215
|
+
n = len(chain)
|
|
216
|
+
if n > 1 and reduction:
|
|
217
|
+
# OpenACC 3.4 §2.6.2 p.41: a reduction variable of a loop in a
|
|
218
|
+
# parallel construct must be in a data clause of the construct;
|
|
219
|
+
# OpenMP: a reduction on a construct nested in target (not a
|
|
220
|
+
# combined target construct) needs the variable mapped tofrom
|
|
221
|
+
# (otherwise it is firstprivate on target: 5.2 §5.8.1 p.148)
|
|
222
|
+
data = list(data) + [(v, "tofrom") for _, items in reduction
|
|
223
|
+
for v in items]
|
|
224
|
+
if n > 1 and o.model == "omp":
|
|
225
|
+
lp = [a for a in loop_extra if a.startswith("lastprivate(")]
|
|
226
|
+
for v in [x.strip(",)") for a in lp for x in
|
|
227
|
+
a[len("lastprivate("):].split()]:
|
|
228
|
+
data = list(data) + [(v, "tofrom")]
|
|
229
|
+
fp_first = o.model == "acc" and n > 1
|
|
230
|
+
for k, d in enumerate(chain):
|
|
231
|
+
atoms = []
|
|
232
|
+
if k == 0:
|
|
233
|
+
atoms += data_clauses(o, list(data)) + list(extra)
|
|
234
|
+
if fp_first:
|
|
235
|
+
# OpenACC: firstprivate is a compute-construct clause
|
|
236
|
+
# (3.4 §2.5.14), not a loop clause
|
|
237
|
+
atoms += list_atoms("firstprivate", list(firstprivate))
|
|
238
|
+
if k < n - 1 and "teams" in d.split() and reduction:
|
|
239
|
+
# the teams of a split nest would race on the shared variable:
|
|
240
|
+
# the reduction is on the teams construct too
|
|
241
|
+
for op, items in reduction:
|
|
242
|
+
atoms += list_atoms("reduction", list(items), op)
|
|
243
|
+
if k == n - 1:
|
|
244
|
+
if collapse > 1:
|
|
245
|
+
atoms.append(f"collapse({collapse})")
|
|
246
|
+
atoms += list_atoms("private", list(private))
|
|
247
|
+
if not fp_first:
|
|
248
|
+
atoms += list_atoms("firstprivate", list(firstprivate))
|
|
249
|
+
for op, items in reduction:
|
|
250
|
+
atoms += list_atoms("reduction", list(items), op)
|
|
251
|
+
atoms += list(loop_extra)
|
|
252
|
+
opens += pack(d, atoms, ind, o.sent, o.width)
|
|
253
|
+
dname = d if o.model == "omp" else " ".join(
|
|
254
|
+
w for w in d.split() if w in ("parallel", "kernels", "serial",
|
|
255
|
+
"loop"))
|
|
256
|
+
closes.insert(0, f"{ind}{o.sent} end {dname}")
|
|
257
|
+
if k < n - 1:
|
|
258
|
+
ind += " "
|
|
259
|
+
if o.model == "acc":
|
|
260
|
+
# an OpenACC loop construct has no end directive; a combined
|
|
261
|
+
# construct's is optional (written), a compute construct's required
|
|
262
|
+
closes = [c for c, d in zip(closes, reversed(chain))
|
|
263
|
+
if " loop" not in " " + d or d.split()[0] in
|
|
264
|
+
("parallel", "kernels", "serial")]
|
|
265
|
+
return opens, closes, ind
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
# --- kernels -----------------------------------------------------------------------------------
|
|
269
|
+
|
|
270
|
+
@dataclass
|
|
271
|
+
class Module:
|
|
272
|
+
name: str
|
|
273
|
+
spec: list[str] = field(default_factory=list)
|
|
274
|
+
contains: list[str] = field(default_factory=list)
|
|
275
|
+
uses: list[str] = field(default_factory=list)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class Kernel:
|
|
279
|
+
"""One kernel: a subroutine ``<name>(cs)`` of a kernel module. Every
|
|
280
|
+
random decision is made in the constructor (``self.p``), so the text
|
|
281
|
+
and the value are functions of ``p``; ``smaller`` returns variants for
|
|
282
|
+
the shrinker."""
|
|
283
|
+
kind = "base"
|
|
284
|
+
legality = "legal"
|
|
285
|
+
cite = ""
|
|
286
|
+
version = 50 # the OpenMP version whose text it needs
|
|
287
|
+
# whether the sequential elision computes the kernel's value (False
|
|
288
|
+
# where the value depends on data-sharing: a firstprivate copy's write
|
|
289
|
+
# is not seen by the host, the elided program writes the variable)
|
|
290
|
+
elision_valid = True
|
|
291
|
+
|
|
292
|
+
def __init__(self, name: str, o: Opts, rng: random.Random | None,
|
|
293
|
+
**p):
|
|
294
|
+
self.name, self.o = name, o
|
|
295
|
+
self.p = dict(p)
|
|
296
|
+
if rng is not None:
|
|
297
|
+
self.draw(rng)
|
|
298
|
+
|
|
299
|
+
def draw(self, rng: random.Random) -> None:
|
|
300
|
+
pass
|
|
301
|
+
|
|
302
|
+
def clone(self, **change) -> "Kernel":
|
|
303
|
+
k = type(self)(self.name, self.o, None, **{**self.p, **change})
|
|
304
|
+
return k
|
|
305
|
+
|
|
306
|
+
# text
|
|
307
|
+
def modules(self) -> list[Module]:
|
|
308
|
+
return []
|
|
309
|
+
|
|
310
|
+
def uses(self) -> list[str]:
|
|
311
|
+
return []
|
|
312
|
+
|
|
313
|
+
def decls(self) -> list[str]:
|
|
314
|
+
return []
|
|
315
|
+
|
|
316
|
+
def body(self) -> list[str]:
|
|
317
|
+
return []
|
|
318
|
+
|
|
319
|
+
def value(self) -> int:
|
|
320
|
+
raise NotImplementedError
|
|
321
|
+
|
|
322
|
+
def smaller(self) -> list["Kernel"]:
|
|
323
|
+
return []
|
|
324
|
+
|
|
325
|
+
def features(self) -> set:
|
|
326
|
+
return {f"kernel:{self.kind}"}
|
|
327
|
+
|
|
328
|
+
def describe(self) -> str:
|
|
329
|
+
def show(v):
|
|
330
|
+
if isinstance(v, list) and len(v) <= 6 and all(
|
|
331
|
+
isinstance(x, int) for x in v):
|
|
332
|
+
return "x".join(map(str, v))
|
|
333
|
+
if isinstance(v, list) and all(isinstance(x, str) for x in v):
|
|
334
|
+
return "+".join(v) if len(v) <= 4 else f"{len(v)}items"
|
|
335
|
+
return v
|
|
336
|
+
keys = ",".join(f"{k}={show(v)}" for k, v in sorted(self.p.items())
|
|
337
|
+
if (isinstance(v, (int, str)) or k in ("ext",
|
|
338
|
+
"routes"))
|
|
339
|
+
and k != "seed")
|
|
340
|
+
return f"{self.name}:{self.kind}({keys})"
|
|
341
|
+
|
|
342
|
+
def routine(self) -> list[str]:
|
|
343
|
+
ind = " "
|
|
344
|
+
lines = [f" subroutine {self.name}(cs)"]
|
|
345
|
+
for u in self.uses():
|
|
346
|
+
lines.append(f"{ind}use {u}")
|
|
347
|
+
lines += [f"{ind}implicit none", f"{ind}integer(8), intent(out) :: cs"]
|
|
348
|
+
lines += [ind + d if not d.startswith(" ") else d
|
|
349
|
+
for d in self.decls()]
|
|
350
|
+
lines += self.body()
|
|
351
|
+
lines.append(f" end subroutine {self.name}")
|
|
352
|
+
return lines
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _halve(n: int, lo: int = 1) -> list[int]:
|
|
356
|
+
out = []
|
|
357
|
+
for m in (lo, n // 2):
|
|
358
|
+
if lo <= m < n and m not in out:
|
|
359
|
+
out.append(m)
|
|
360
|
+
return out
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
class LoopKernel(Kernel):
|
|
364
|
+
"""out(i) = mod(a(i)*c1 + i*c2 + c3, 1000003) over a random chain."""
|
|
365
|
+
kind = "loop"
|
|
366
|
+
|
|
367
|
+
def draw(self, rng):
|
|
368
|
+
chains = OMP_CHAINS if self.o.model == "omp" else ACC_CHAINS
|
|
369
|
+
self.p.setdefault("chain", rng.randrange(len(chains)))
|
|
370
|
+
self.p.setdefault("n", rng.choice((64, 100, 257, 1000, 4096)))
|
|
371
|
+
self.p.setdefault("c", [rng.randrange(1, 1000) for _ in range(3)])
|
|
372
|
+
|
|
373
|
+
def chain(self):
|
|
374
|
+
chains = OMP_CHAINS if self.o.model == "omp" else ACC_CHAINS
|
|
375
|
+
return chains[self.p["chain"] % len(chains)]
|
|
376
|
+
|
|
377
|
+
def decls(self):
|
|
378
|
+
n = self.p["n"]
|
|
379
|
+
return [f"integer(8) :: a({n}), out({n})", "integer :: i"]
|
|
380
|
+
|
|
381
|
+
def body(self):
|
|
382
|
+
n, (c1, c2, c3) = self.p["n"], self.p["c"]
|
|
383
|
+
ind = " "
|
|
384
|
+
lines = [f"{ind}do i = 1, {n}", f"{ind} a(i) = mod(i * 37, 1009)",
|
|
385
|
+
f"{ind}end do", f"{ind}out = 0"]
|
|
386
|
+
op, cl, ii = region(self.o, self.chain(), ind,
|
|
387
|
+
data=[("a", "to"), ("out", "tofrom")])
|
|
388
|
+
lines += op + [f"{ii}do i = 1, {n}",
|
|
389
|
+
f"{ii} out(i) = mod(a(i) * {c1} + i * {c2} + {c3}, "
|
|
390
|
+
"1000003_8)", f"{ii}end do"] + cl
|
|
391
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
392
|
+
return lines
|
|
393
|
+
|
|
394
|
+
def value(self):
|
|
395
|
+
n, (c1, c2, c3) = self.p["n"], self.p["c"]
|
|
396
|
+
return cksum(fmod((i * 37 % 1009) * c1 + i * c2 + c3, 1000003)
|
|
397
|
+
for i in range(1, n + 1))
|
|
398
|
+
|
|
399
|
+
def smaller(self):
|
|
400
|
+
return [self.clone(n=m) for m in _halve(self.p["n"], 8)] + (
|
|
401
|
+
[self.clone(chain=0)] if self.p["chain"] else [])
|
|
402
|
+
|
|
403
|
+
def features(self):
|
|
404
|
+
return super().features() | {"chain:" + " | ".join(self.chain())}
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
class NestKernel(Kernel):
|
|
408
|
+
"""A loop nest `depth` deep; collapse(c) on the loop directive (c up
|
|
409
|
+
to the depth); out(lin) = sum_k idx_k * w_k + c0 where lin is the
|
|
410
|
+
linear index of the full nest; optional split: teams distribute over
|
|
411
|
+
the outermost loop, a nested parallel do (collapse) over the next, simd
|
|
412
|
+
on the innermost."""
|
|
413
|
+
kind = "nest"
|
|
414
|
+
|
|
415
|
+
def draw(self, rng):
|
|
416
|
+
d = self.p.setdefault("depth", 3)
|
|
417
|
+
# past 16 levels the extra levels run once (2**16 iterations at
|
|
418
|
+
# most from extents of 2): the nest depth is the stress, not the
|
|
419
|
+
# iteration count
|
|
420
|
+
ext = self.p.setdefault("ext", [rng.choice((2, 3, 4, 5)) if k < 16
|
|
421
|
+
else 1 for k in range(d)])
|
|
422
|
+
tot = 1
|
|
423
|
+
for e in ext:
|
|
424
|
+
tot *= e
|
|
425
|
+
while tot > 200000:
|
|
426
|
+
k = max(range(d), key=lambda j: ext[j])
|
|
427
|
+
ext[k] = max(min(2, ext[k]), ext[k] - 1)
|
|
428
|
+
tot = 1
|
|
429
|
+
for e in ext:
|
|
430
|
+
tot *= e
|
|
431
|
+
if all(e <= 2 for e in ext):
|
|
432
|
+
break
|
|
433
|
+
self.p.setdefault("collapse", rng.choice(
|
|
434
|
+
(d, d, max(1, d - 1), 1)) if d > 1 else 1)
|
|
435
|
+
self.p.setdefault("split", rng.random() < 0.4 and d >= 3)
|
|
436
|
+
self.p.setdefault("w", [rng.randrange(1, 50) for _ in range(d)])
|
|
437
|
+
self.p.setdefault("c0", rng.randrange(1000))
|
|
438
|
+
|
|
439
|
+
def total(self):
|
|
440
|
+
t = 1
|
|
441
|
+
for e in self.p["ext"]:
|
|
442
|
+
t *= e
|
|
443
|
+
return t
|
|
444
|
+
|
|
445
|
+
def decls(self):
|
|
446
|
+
d = self.p["depth"]
|
|
447
|
+
return [f"integer(8) :: out({self.total()})",
|
|
448
|
+
*decl_lines("integer", [f"i{k}" for k in range(1, d + 1)],
|
|
449
|
+
self.o.width), "integer :: lin"]
|
|
450
|
+
|
|
451
|
+
def _lin(self):
|
|
452
|
+
ext = self.p["ext"]
|
|
453
|
+
terms, stride = [], 1
|
|
454
|
+
for k in range(len(ext), 0, -1):
|
|
455
|
+
terms.append(f"(i{k} - 1) * {stride}" if stride > 1
|
|
456
|
+
else f"(i{k} - 1)")
|
|
457
|
+
stride *= ext[k - 1]
|
|
458
|
+
return " + ".join(reversed(terms)) + " + 1"
|
|
459
|
+
|
|
460
|
+
def _lin_lines(self, ind, expr):
|
|
461
|
+
lin = self._lin().split(" + ")
|
|
462
|
+
terms = expr.split(" + ")
|
|
463
|
+
return pack("lin =", [t + (" +" if k < len(lin) - 1 else "")
|
|
464
|
+
for k, t in enumerate(lin)], ind, None,
|
|
465
|
+
self.o.width) + \
|
|
466
|
+
pack("out(lin) =", [t + (" +" if k < len(terms) - 1 else "")
|
|
467
|
+
for k, t in enumerate(terms)], ind, None,
|
|
468
|
+
self.o.width)
|
|
469
|
+
|
|
470
|
+
def body(self):
|
|
471
|
+
d, ext, w, c0 = (self.p["depth"], self.p["ext"], self.p["w"],
|
|
472
|
+
self.p["c0"])
|
|
473
|
+
col = self.p["collapse"]
|
|
474
|
+
ind = " "
|
|
475
|
+
lines = [f"{ind}out = 0"]
|
|
476
|
+
priv = [f"i{k}" for k in range(col + 1, d + 1)] + ["lin"]
|
|
477
|
+
expr = " + ".join(f"i{k} * {w[k - 1]}" for k in range(1, d + 1)) + \
|
|
478
|
+
f" + {c0}"
|
|
479
|
+
if self.p["split"] and self.o.model == "omp":
|
|
480
|
+
# teams distribute over i1; parallel do collapse over the rest
|
|
481
|
+
# (up to the collapse depth); simd on nothing (bodies index out)
|
|
482
|
+
inner_col = max(1, min(col, d - 1))
|
|
483
|
+
op1, cl1, i1 = region(self.o, ("target teams distribute",), ind,
|
|
484
|
+
data=[("out", "tofrom")])
|
|
485
|
+
lines += op1 + [f"{i1}do i1 = 1, {ext[0]}"]
|
|
486
|
+
inner_priv = [f"i{k}" for k in range(2 + inner_col, d + 1)] + \
|
|
487
|
+
["lin"]
|
|
488
|
+
op2, cl2, i2 = region(self.o, ("parallel do",), i1 + " ",
|
|
489
|
+
private=inner_priv, collapse=inner_col)
|
|
490
|
+
lines += op2
|
|
491
|
+
def at(k): # indentation, capped (deep nests stay < 132)
|
|
492
|
+
return i2 + " " * min(k - 2, 16)
|
|
493
|
+
for k in range(2, d + 1):
|
|
494
|
+
lines.append(f"{at(k)}do i{k} = 1, {ext[k - 1]}")
|
|
495
|
+
lines += self._lin_lines(at(d + 1), expr)
|
|
496
|
+
for k in range(d, 1, -1):
|
|
497
|
+
lines.append(f"{at(k)}end do")
|
|
498
|
+
lines += cl2 + [f"{i1}end do"] + cl1
|
|
499
|
+
else:
|
|
500
|
+
chain = ("target teams distribute parallel do",) if \
|
|
501
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
502
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")],
|
|
503
|
+
private=priv, collapse=col)
|
|
504
|
+
lines += op
|
|
505
|
+
|
|
506
|
+
def at(k):
|
|
507
|
+
return ii + " " * min(k - 1, 16)
|
|
508
|
+
for k in range(1, d + 1):
|
|
509
|
+
lines.append(f"{at(k)}do i{k} = 1, {ext[k - 1]}")
|
|
510
|
+
lines += self._lin_lines(at(d + 1), expr)
|
|
511
|
+
for k in range(d, 0, -1):
|
|
512
|
+
lines.append(f"{at(k)}end do")
|
|
513
|
+
lines += cl
|
|
514
|
+
lines.append(f"{ind}call st_cksum(out, {self.total()}, cs)")
|
|
515
|
+
return lines
|
|
516
|
+
|
|
517
|
+
def value(self):
|
|
518
|
+
import itertools
|
|
519
|
+
ext, w, c0 = self.p["ext"], self.p["w"], self.p["c0"]
|
|
520
|
+
out = [0] * self.total()
|
|
521
|
+
for idx in itertools.product(*[range(1, e + 1) for e in ext]):
|
|
522
|
+
lin, stride = 0, 1
|
|
523
|
+
for k in range(len(ext) - 1, -1, -1):
|
|
524
|
+
lin += (idx[k] - 1) * stride
|
|
525
|
+
stride *= ext[k]
|
|
526
|
+
out[lin] = sum(i * wk for i, wk in zip(idx, w)) + c0
|
|
527
|
+
return cksum(out)
|
|
528
|
+
|
|
529
|
+
def smaller(self):
|
|
530
|
+
d = self.p["depth"]
|
|
531
|
+
out = []
|
|
532
|
+
if d > 1:
|
|
533
|
+
out.append(self.clone(depth=d - 1, ext=self.p["ext"][:-1],
|
|
534
|
+
w=self.p["w"][:-1],
|
|
535
|
+
collapse=min(self.p["collapse"], d - 1),
|
|
536
|
+
split=self.p["split"] and d - 1 >= 3))
|
|
537
|
+
if self.p["collapse"] > 1:
|
|
538
|
+
out.append(self.clone(collapse=1))
|
|
539
|
+
if self.p["split"]:
|
|
540
|
+
out.append(self.clone(split=False))
|
|
541
|
+
if any(e > 2 for e in self.p["ext"]):
|
|
542
|
+
out.append(self.clone(ext=[min(2, e) for e in self.p["ext"]]))
|
|
543
|
+
return out
|
|
544
|
+
|
|
545
|
+
def features(self):
|
|
546
|
+
f = super().features() | {f"nest:depth{self.p['depth']}",
|
|
547
|
+
f"nest:collapse{self.p['collapse']}"}
|
|
548
|
+
if self.p["collapse"] == self.p["depth"]:
|
|
549
|
+
f.add("nest:collapse_full")
|
|
550
|
+
if self.p["split"]:
|
|
551
|
+
f.add("nest:split")
|
|
552
|
+
return f
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def _item_count(size: int) -> int:
|
|
556
|
+
return max(1, int(size))
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
class ListKernel(Kernel):
|
|
560
|
+
"""Base of the list axes: `nitems` items, `n` iterations (n * items is
|
|
561
|
+
kept below 2e5 so the model stays fast)."""
|
|
562
|
+
kind = "list"
|
|
563
|
+
|
|
564
|
+
def draw(self, rng):
|
|
565
|
+
k = self.p.setdefault("nitems", 8)
|
|
566
|
+
self.p.setdefault("n", max(8, min(256, 200000 // max(1, k))))
|
|
567
|
+
self.p.setdefault("chain", rng.randrange(3))
|
|
568
|
+
self.p.setdefault("c", [rng.randrange(1, 97) for _ in range(k)])
|
|
569
|
+
|
|
570
|
+
def items(self, prefix):
|
|
571
|
+
return [vname(prefix, k) for k in range(1, self.p["nitems"] + 1)]
|
|
572
|
+
|
|
573
|
+
def smaller(self):
|
|
574
|
+
k = self.p["nitems"]
|
|
575
|
+
out = []
|
|
576
|
+
for m in _halve(k):
|
|
577
|
+
out.append(self.clone(nitems=m, c=self.p["c"][:m]))
|
|
578
|
+
if self.p["n"] > 8:
|
|
579
|
+
out.append(self.clone(n=8))
|
|
580
|
+
return out
|
|
581
|
+
|
|
582
|
+
def chain(self):
|
|
583
|
+
if self.o.model == "omp":
|
|
584
|
+
return (("target teams distribute parallel do",),
|
|
585
|
+
("target parallel do",),
|
|
586
|
+
("target", "teams distribute parallel do"))[
|
|
587
|
+
self.p["chain"] % 3]
|
|
588
|
+
return (("parallel loop gang vector",), ("parallel loop",),
|
|
589
|
+
("parallel", "loop gang vector"))[self.p["chain"] % 3]
|
|
590
|
+
|
|
591
|
+
def features(self):
|
|
592
|
+
return super().features() | {
|
|
593
|
+
f"list:{self.kind}", f"len:{self.kind}:{self.p['nitems']}"}
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
class PrivateKernel(ListKernel):
|
|
597
|
+
"""private(p0001, ..., pN): each iteration sets every p_j and sums
|
|
598
|
+
them (a shared p_j would race)."""
|
|
599
|
+
kind = "private"
|
|
600
|
+
|
|
601
|
+
def decls(self):
|
|
602
|
+
n = self.p["n"]
|
|
603
|
+
its = self.items("p")
|
|
604
|
+
return [f"integer(8) :: out({n})", "integer :: i", "integer(8) :: t"] \
|
|
605
|
+
+ [ln.strip() for ln in pack("integer(8) ::",
|
|
606
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
607
|
+
for k, x in enumerate(its)], "",
|
|
608
|
+
None, self.o.width)]
|
|
609
|
+
|
|
610
|
+
def body(self):
|
|
611
|
+
n, c = self.p["n"], self.p["c"]
|
|
612
|
+
its = self.items("p")
|
|
613
|
+
ind = " "
|
|
614
|
+
lines = [f"{ind}out = 0"]
|
|
615
|
+
op, cl, ii = region(self.o, self.chain(), ind,
|
|
616
|
+
data=[("out", "tofrom")], private=its + ["t"])
|
|
617
|
+
lines += op + [f"{ii}do i = 1, {n}"]
|
|
618
|
+
for k, x in enumerate(its):
|
|
619
|
+
lines.append(f"{ii} {x} = mod(i * {c[k]} + {k + 1}, 997)")
|
|
620
|
+
lines.append(f"{ii} t = 0")
|
|
621
|
+
lines += sum_lines(ii + " ", "t", its, self.o.width)
|
|
622
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do"] + cl
|
|
623
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
624
|
+
return lines
|
|
625
|
+
|
|
626
|
+
def value(self):
|
|
627
|
+
n, c = self.p["n"], self.p["c"]
|
|
628
|
+
k = self.p["nitems"]
|
|
629
|
+
return cksum(sum((i * c[j] + j + 1) % 997 for j in range(k))
|
|
630
|
+
for i in range(1, n + 1))
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
class FirstprivateKernel(ListKernel):
|
|
634
|
+
"""firstprivate(f0001, ..., fN) of host-initialised scalars; the device
|
|
635
|
+
reads each; the host values must be unchanged afterwards."""
|
|
636
|
+
kind = "firstprivate"
|
|
637
|
+
|
|
638
|
+
def decls(self):
|
|
639
|
+
n = self.p["n"]
|
|
640
|
+
its = self.items("f")
|
|
641
|
+
return [f"integer(8) :: out({n})", "integer :: i", "integer(8) :: t"] \
|
|
642
|
+
+ [ln.strip() for ln in pack("integer(8) ::",
|
|
643
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
644
|
+
for k, x in enumerate(its)], "",
|
|
645
|
+
None, self.o.width)]
|
|
646
|
+
|
|
647
|
+
def body(self):
|
|
648
|
+
n, c = self.p["n"], self.p["c"]
|
|
649
|
+
its = self.items("f")
|
|
650
|
+
ind = " "
|
|
651
|
+
lines = [f"{ind}{x} = {c[k] * 7 + k}" for k, x in enumerate(its)]
|
|
652
|
+
lines.append(f"{ind}out = 0")
|
|
653
|
+
op, cl, ii = region(self.o, self.chain(), ind,
|
|
654
|
+
data=[("out", "tofrom")], private=["t"],
|
|
655
|
+
firstprivate=its)
|
|
656
|
+
lines += op + [f"{ii}do i = 1, {n}", f"{ii} t = 0"]
|
|
657
|
+
terms = [f"{x} * mod(i + {k}, 3)" for k, x in enumerate(its)]
|
|
658
|
+
lines += sum_lines(ii + " ", "t", terms, self.o.width)
|
|
659
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do"] + cl
|
|
660
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
661
|
+
lines.append(f"{ind}t = 0")
|
|
662
|
+
lines += sum_lines(ind, "t", its, self.o.width)
|
|
663
|
+
lines.append(f"{ind}cs = mod(cs + t, {P}_8)")
|
|
664
|
+
return lines
|
|
665
|
+
|
|
666
|
+
def value(self):
|
|
667
|
+
n, c = self.p["n"], self.p["c"]
|
|
668
|
+
k = self.p["nitems"]
|
|
669
|
+
f = [c[j] * 7 + j for j in range(k)]
|
|
670
|
+
cs = cksum(sum(f[j] * ((i + j) % 3) for j in range(k))
|
|
671
|
+
for i in range(1, n + 1))
|
|
672
|
+
return (cs + sum(f)) % P
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
class LastprivateKernel(ListKernel):
|
|
676
|
+
"""lastprivate(l0001, ..., lN): after the loop l_j holds the value of
|
|
677
|
+
the sequentially last iteration, n * c_j + j."""
|
|
678
|
+
kind = "lastprivate"
|
|
679
|
+
|
|
680
|
+
def decls(self):
|
|
681
|
+
its = self.items("l")
|
|
682
|
+
return ["integer :: i", "integer(8) :: t"] + \
|
|
683
|
+
[ln.strip() for ln in pack("integer(8) ::",
|
|
684
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
685
|
+
for k, x in enumerate(its)], "",
|
|
686
|
+
None, self.o.width)]
|
|
687
|
+
|
|
688
|
+
def chain(self):
|
|
689
|
+
if self.o.model == "omp":
|
|
690
|
+
# lastprivate on a combined target construct: the list item is
|
|
691
|
+
# treated as if it also appeared in map(tofrom) (5.0 §2.19.7.1)
|
|
692
|
+
return (("target teams distribute parallel do",),
|
|
693
|
+
("target parallel do",),
|
|
694
|
+
("target parallel do",))[self.p["chain"] % 3]
|
|
695
|
+
raise ValueError("OpenACC has no lastprivate clause")
|
|
696
|
+
|
|
697
|
+
def body(self):
|
|
698
|
+
n, c = self.p["n"], self.p["c"]
|
|
699
|
+
its = self.items("l")
|
|
700
|
+
ind = " "
|
|
701
|
+
lines = [f"{ind}{x} = 0" for x in its]
|
|
702
|
+
op, cl, ii = region(self.o, self.chain()[:1], ind,
|
|
703
|
+
loop_extra=list_atoms("lastprivate", its))
|
|
704
|
+
lines += op + [f"{ii}do i = 1, {n}"]
|
|
705
|
+
for k, x in enumerate(its):
|
|
706
|
+
lines.append(f"{ii} {x} = i * {c[k]} + {k}")
|
|
707
|
+
lines += [f"{ii}end do"] + cl
|
|
708
|
+
lines.append(f"{ind}t = 0")
|
|
709
|
+
lines += sum_lines(ind, "t", its, self.o.width)
|
|
710
|
+
lines.append(f"{ind}cs = mod(t, {P}_8)")
|
|
711
|
+
return lines
|
|
712
|
+
|
|
713
|
+
def value(self):
|
|
714
|
+
n, c = self.p["n"], self.p["c"]
|
|
715
|
+
return sum(n * c[j] + j for j in range(self.p["nitems"])) % P
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
class SharedKernel(ListKernel):
|
|
719
|
+
"""target data region; inside, ``parallel do shared(s0001..sN, out)``
|
|
720
|
+
nested in a target region (shared is a parallel / teams clause): the
|
|
721
|
+
shared scalars are read by every thread."""
|
|
722
|
+
kind = "shared"
|
|
723
|
+
|
|
724
|
+
def decls(self):
|
|
725
|
+
n = self.p["n"]
|
|
726
|
+
its = self.items("s")
|
|
727
|
+
return [f"integer(8) :: out({n})", "integer :: i", "integer(8) :: t"] \
|
|
728
|
+
+ [ln.strip() for ln in pack("integer(8) ::",
|
|
729
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
730
|
+
for k, x in enumerate(its)], "",
|
|
731
|
+
None, self.o.width)]
|
|
732
|
+
|
|
733
|
+
def body(self):
|
|
734
|
+
n, c = self.p["n"], self.p["c"]
|
|
735
|
+
its = self.items("s")
|
|
736
|
+
ind = " "
|
|
737
|
+
lines = [f"{ind}{x} = {c[k] + k}" for k, x in enumerate(its)]
|
|
738
|
+
lines.append(f"{ind}out = 0")
|
|
739
|
+
if self.o.model == "omp":
|
|
740
|
+
op1 = pack("target", data_clauses(self.o, [(x, "to") for x in
|
|
741
|
+
its] +
|
|
742
|
+
[("out", "tofrom")]),
|
|
743
|
+
ind, self.o.sent, self.o.width)
|
|
744
|
+
op2 = pack("parallel do", list_atoms("shared", its + ["out"]) +
|
|
745
|
+
list_atoms("private", ["t"]), ind + " ",
|
|
746
|
+
self.o.sent, self.o.width)
|
|
747
|
+
ii = ind + " "
|
|
748
|
+
lines += op1 + op2 + [f"{ii}do i = 1, {n}", f"{ii} t = 0"]
|
|
749
|
+
terms = [f"{x} * mod(i, {k + 2})" for k, x in enumerate(its)]
|
|
750
|
+
lines += sum_lines(ii + " ", "t", terms, self.o.width)
|
|
751
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do",
|
|
752
|
+
f"{ind} {self.o.sent} end parallel do",
|
|
753
|
+
f"{ind}{self.o.sent} end target"]
|
|
754
|
+
else:
|
|
755
|
+
op, cl, ii = region(self.o, ("parallel loop",), ind,
|
|
756
|
+
data=[(x, "to") for x in its] +
|
|
757
|
+
[("out", "tofrom")], private=["t"])
|
|
758
|
+
lines += op + [f"{ii}do i = 1, {n}", f"{ii} t = 0"]
|
|
759
|
+
terms = [f"{x} * mod(i, {k + 2})" for k, x in enumerate(its)]
|
|
760
|
+
lines += sum_lines(ii + " ", "t", terms, self.o.width)
|
|
761
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do"] + cl
|
|
762
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
763
|
+
return lines
|
|
764
|
+
|
|
765
|
+
def value(self):
|
|
766
|
+
n, c = self.p["n"], self.p["c"]
|
|
767
|
+
k = self.p["nitems"]
|
|
768
|
+
s = [c[j] + j for j in range(k)]
|
|
769
|
+
return cksum(sum(s[j] * (i % (j + 2)) for j in range(k))
|
|
770
|
+
for i in range(1, n + 1))
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
class MapKernel(ListKernel):
|
|
774
|
+
"""map(to: a0001..aN) map(tofrom: b0001..bN): N arrays of m elements;
|
|
775
|
+
b_j(i) = b_j(i) + a_j(i) * c_j."""
|
|
776
|
+
kind = "map"
|
|
777
|
+
|
|
778
|
+
def draw(self, rng):
|
|
779
|
+
k = self.p.setdefault("nitems", 8)
|
|
780
|
+
self.p.setdefault("m", max(4, min(64, 100000 // max(1, k))))
|
|
781
|
+
self.p.setdefault("n", self.p["m"])
|
|
782
|
+
self.p.setdefault("chain", rng.randrange(3))
|
|
783
|
+
self.p.setdefault("c", [rng.randrange(1, 97) for _ in range(k)])
|
|
784
|
+
|
|
785
|
+
def decls(self):
|
|
786
|
+
m = self.p["m"]
|
|
787
|
+
its_a, its_b = self.items("a"), self.items("b")
|
|
788
|
+
ents = [f"{x}({m})" for x in its_a + its_b]
|
|
789
|
+
return ["integer :: i", "integer(8) :: t"] + \
|
|
790
|
+
[ln.strip() for ln in pack("integer(8) ::",
|
|
791
|
+
[x + ("," if k < len(ents) - 1 else "")
|
|
792
|
+
for k, x in enumerate(ents)], "",
|
|
793
|
+
None, self.o.width)]
|
|
794
|
+
|
|
795
|
+
def body(self):
|
|
796
|
+
m, c = self.p["m"], self.p["c"]
|
|
797
|
+
A, B = self.items("a"), self.items("b")
|
|
798
|
+
ind = " "
|
|
799
|
+
lines = [f"{ind}do i = 1, {m}"]
|
|
800
|
+
for k in range(len(A)):
|
|
801
|
+
lines.append(f"{ind} {A[k]}(i) = mod(i * {k + 3}, 101)")
|
|
802
|
+
lines.append(f"{ind} {B[k]}(i) = {k}")
|
|
803
|
+
lines.append(f"{ind}end do")
|
|
804
|
+
op, cl, ii = region(self.o, self.chain(), ind,
|
|
805
|
+
data=[(x, "to") for x in A] +
|
|
806
|
+
[(x, "tofrom") for x in B])
|
|
807
|
+
lines += op + [f"{ii}do i = 1, {m}"]
|
|
808
|
+
for k in range(len(A)):
|
|
809
|
+
lines.append(f"{ii} {B[k]}(i) = {B[k]}(i) + {A[k]}(i) * {c[k]}")
|
|
810
|
+
lines += [f"{ii}end do"] + cl
|
|
811
|
+
lines.append(f"{ind}cs = 0")
|
|
812
|
+
for k in range(len(B)):
|
|
813
|
+
lines.append(f"{ind}call st_cksum({B[k]}, {m}, t)")
|
|
814
|
+
lines.append(f"{ind}cs = mod(cs * 31 + t, {P}_8)")
|
|
815
|
+
return lines
|
|
816
|
+
|
|
817
|
+
def value(self):
|
|
818
|
+
m, c = self.p["m"], self.p["c"]
|
|
819
|
+
cs = 0
|
|
820
|
+
for k in range(self.p["nitems"]):
|
|
821
|
+
t = cksum(k + ((i * (k + 3)) % 101) * c[k]
|
|
822
|
+
for i in range(1, m + 1))
|
|
823
|
+
cs = (cs * 31 + t) % P
|
|
824
|
+
return cs
|
|
825
|
+
|
|
826
|
+
def smaller(self):
|
|
827
|
+
k = self.p["nitems"]
|
|
828
|
+
return [self.clone(nitems=m, c=self.p["c"][:m]) for m in _halve(k)] \
|
|
829
|
+
+ ([self.clone(m=4, n=4)] if self.p["m"] > 4 else [])
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
RED_OPS = ("+", "*", "max", "min", "iand", "ior", "ieor")
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
class ReductionKernel(ListKernel):
|
|
836
|
+
"""reduction clauses over r0001..rN with operators cycling through
|
|
837
|
+
+ * max min iand ior ieor (one clause per operator); * multiplies by 2
|
|
838
|
+
on 3 iterations only (bounded)."""
|
|
839
|
+
kind = "reduction"
|
|
840
|
+
|
|
841
|
+
def draw(self, rng):
|
|
842
|
+
super().draw(rng)
|
|
843
|
+
self.p.setdefault("ops", [RED_OPS[(j + rng.randrange(7)) % 7]
|
|
844
|
+
for j in range(self.p["nitems"])])
|
|
845
|
+
|
|
846
|
+
def decls(self):
|
|
847
|
+
its = self.items("r")
|
|
848
|
+
return ["integer :: i", "integer(8) :: t"] + \
|
|
849
|
+
[ln.strip() for ln in pack("integer(8) ::",
|
|
850
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
851
|
+
for k, x in enumerate(its)], "",
|
|
852
|
+
None, self.o.width)]
|
|
853
|
+
|
|
854
|
+
def init(self, op, k):
|
|
855
|
+
return {"+": k, "*": 1, "max": 0, "min": 1000000, "iand": 1048575,
|
|
856
|
+
"ior": 0, "ieor": k}[op]
|
|
857
|
+
|
|
858
|
+
def contrib(self, op, i, k, c):
|
|
859
|
+
if op == "*":
|
|
860
|
+
return f"merge(2_8, 1_8, mod(i, {max(1, self.p['n'] // 3)}) == 0" \
|
|
861
|
+
f" .and. i <= {3 * max(1, self.p['n'] // 3)})"
|
|
862
|
+
return f"int(mod(i * {c} + {k}, 65536), 8)"
|
|
863
|
+
|
|
864
|
+
def body(self):
|
|
865
|
+
n, c, ops = self.p["n"], self.p["c"], self.p["ops"]
|
|
866
|
+
its = self.items("r")
|
|
867
|
+
ind = " "
|
|
868
|
+
lines = [f"{ind}{x} = {self.init(ops[k], k)}"
|
|
869
|
+
for k, x in enumerate(its)]
|
|
870
|
+
groups: dict[str, list[str]] = {}
|
|
871
|
+
for k, x in enumerate(its):
|
|
872
|
+
groups.setdefault(ops[k], []).append(x)
|
|
873
|
+
red = [(op, groups[op]) for op in RED_OPS if op in groups]
|
|
874
|
+
op_, cl, ii = region(self.o, self.chain(), ind, reduction=red)
|
|
875
|
+
lines += op_ + [f"{ii}do i = 1, {n}"]
|
|
876
|
+
for k, x in enumerate(its):
|
|
877
|
+
e = self.contrib(ops[k], None, k, c[k])
|
|
878
|
+
stmt = {"+": f"{x} = {x} + {e}", "*": f"{x} = {x} * {e}",
|
|
879
|
+
"max": f"{x} = max({x}, {e})",
|
|
880
|
+
"min": f"{x} = min({x}, {e})",
|
|
881
|
+
"iand": f"{x} = iand({x}, {e} + 1048576_8 - 65536_8)",
|
|
882
|
+
"ior": f"{x} = ior({x}, {e})",
|
|
883
|
+
"ieor": f"{x} = ieor({x}, {e})"}[ops[k]]
|
|
884
|
+
lines.append(f"{ii} {stmt}")
|
|
885
|
+
lines += [f"{ii}end do"] + cl
|
|
886
|
+
lines.append(f"{ind}cs = 0")
|
|
887
|
+
for x in its:
|
|
888
|
+
lines.append(f"{ind}cs = mod(cs * 31 + mod({x}, {P}_8), {P}_8)")
|
|
889
|
+
return lines
|
|
890
|
+
|
|
891
|
+
def value(self):
|
|
892
|
+
n, c, ops = self.p["n"], self.p["c"], self.p["ops"]
|
|
893
|
+
cs = 0
|
|
894
|
+
step = max(1, n // 3)
|
|
895
|
+
for k in range(self.p["nitems"]):
|
|
896
|
+
op = ops[k]
|
|
897
|
+
v = self.init(op, k)
|
|
898
|
+
for i in range(1, n + 1):
|
|
899
|
+
e = (i * c[k] + k) % 65536
|
|
900
|
+
if op == "+":
|
|
901
|
+
v += e
|
|
902
|
+
elif op == "*":
|
|
903
|
+
v *= 2 if (i % step == 0 and i <= 3 * step) else 1
|
|
904
|
+
elif op == "max":
|
|
905
|
+
v = max(v, e)
|
|
906
|
+
elif op == "min":
|
|
907
|
+
v = min(v, e)
|
|
908
|
+
elif op == "iand":
|
|
909
|
+
v &= e + 1048576 - 65536
|
|
910
|
+
elif op == "ior":
|
|
911
|
+
v |= e
|
|
912
|
+
else:
|
|
913
|
+
v ^= e
|
|
914
|
+
chk(v)
|
|
915
|
+
cs = (cs * 31 + v % P) % P
|
|
916
|
+
return cs
|
|
917
|
+
|
|
918
|
+
def smaller(self):
|
|
919
|
+
out = super().smaller()
|
|
920
|
+
for k in out:
|
|
921
|
+
if "ops" in k.p:
|
|
922
|
+
k.p["ops"] = self.p["ops"][:k.p["nitems"]]
|
|
923
|
+
return out
|
|
924
|
+
|
|
925
|
+
def features(self):
|
|
926
|
+
return super().features() | {f"red:{op}" for op in self.p["ops"]}
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
class DependKernel(ListKernel):
|
|
930
|
+
"""T target tasks (nowait) each with depend(inout: d0001..dN) on N
|
|
931
|
+
scalars and map(tofrom: x); the dependences serialize them; taskwait.
|
|
932
|
+
OpenACC: the async queue chain (async(q) wait(q-1)) over N queues."""
|
|
933
|
+
kind = "depend"
|
|
934
|
+
|
|
935
|
+
def draw(self, rng):
|
|
936
|
+
super().draw(rng)
|
|
937
|
+
self.p.setdefault("tasks", 6)
|
|
938
|
+
|
|
939
|
+
def decls(self):
|
|
940
|
+
its = self.items("d")
|
|
941
|
+
return ["integer(8) :: x(4)", "integer :: t"] + \
|
|
942
|
+
[ln.strip() for ln in pack("integer(8) ::",
|
|
943
|
+
[x + ("," if k < len(its) - 1 else "")
|
|
944
|
+
for k, x in enumerate(its)], "",
|
|
945
|
+
None, self.o.width)]
|
|
946
|
+
|
|
947
|
+
def body(self):
|
|
948
|
+
its = self.items("d")
|
|
949
|
+
T = self.p["tasks"]
|
|
950
|
+
ind = " "
|
|
951
|
+
lines = [f"{ind}{x} = 0" for x in its] + [f"{ind}x = 1"]
|
|
952
|
+
if self.o.model == "omp":
|
|
953
|
+
lines.append(f"{ind}do t = 1, {T}")
|
|
954
|
+
lines += pack("target", ["map(tofrom: x)", "nowait"] +
|
|
955
|
+
list_atoms("depend", its, "inout"),
|
|
956
|
+
ind + " ", self.o.sent, self.o.width)
|
|
957
|
+
lines += [f"{ind} x(1) = mod(x(1) * 3 + t, 1000003_8)",
|
|
958
|
+
f"{ind} x(2) = x(1) + t",
|
|
959
|
+
f"{ind} {self.o.sent} end target", f"{ind}end do",
|
|
960
|
+
f"{ind}{self.o.sent} taskwait"]
|
|
961
|
+
else:
|
|
962
|
+
q = len(its)
|
|
963
|
+
lines += [f"{ind}{self.o.sent} enter data copyin(x)",
|
|
964
|
+
f"{ind}do t = 1, {T}"]
|
|
965
|
+
lines += [f"{ind} {self.o.sent} serial present(x) "
|
|
966
|
+
f"async(mod(t - 1, {q}) + 1) "
|
|
967
|
+
f"wait(mod(t + {q} - 2, {q}) + 1)",
|
|
968
|
+
f"{ind} x(1) = mod(x(1) * 3 + t, 1000003_8)",
|
|
969
|
+
f"{ind} x(2) = x(1) + t",
|
|
970
|
+
f"{ind} {self.o.sent} end serial", f"{ind}end do",
|
|
971
|
+
f"{ind}{self.o.sent} wait",
|
|
972
|
+
f"{ind}{self.o.sent} exit data copyout(x)"]
|
|
973
|
+
lines.append(f"{ind}call st_cksum(x, 4, cs)")
|
|
974
|
+
return lines
|
|
975
|
+
|
|
976
|
+
def value(self):
|
|
977
|
+
x = [1, 1, 1, 1]
|
|
978
|
+
for t in range(1, self.p["tasks"] + 1):
|
|
979
|
+
x[0] = (x[0] * 3 + t) % 1000003
|
|
980
|
+
x[1] = x[0] + t
|
|
981
|
+
return cksum(x)
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
class UDRKernel(ListKernel):
|
|
985
|
+
"""A reduction list mixing intrinsic operators with user-defined
|
|
986
|
+
reductions (declare reduction, OpenMP 5.2 §5.5.11): variables cycle
|
|
987
|
+
through +, max, ieor and two user-defined identifiers (a sum and a
|
|
988
|
+
max with an initializer)."""
|
|
989
|
+
kind = "udr"
|
|
990
|
+
OPS = ("+", "max", "ieor", "st_add", "st_max")
|
|
991
|
+
|
|
992
|
+
def decls(self):
|
|
993
|
+
its = self.items("u")
|
|
994
|
+
return ["integer :: i", "integer(8) :: t",
|
|
995
|
+
"!$omp declare reduction(st_add: integer(8): omp_out = "
|
|
996
|
+
"omp_out + omp_in) initializer(omp_priv = 0_8)",
|
|
997
|
+
"!$omp declare reduction(st_max: integer(8): omp_out = "
|
|
998
|
+
"max(omp_out, omp_in)) initializer(omp_priv = -1_8)"] + \
|
|
999
|
+
decl_lines("integer(8)", its, self.o.width)
|
|
1000
|
+
|
|
1001
|
+
def body(self):
|
|
1002
|
+
n, c = self.p["n"], self.p["c"]
|
|
1003
|
+
its = self.items("u")
|
|
1004
|
+
ops = [self.OPS[j % 5] for j in range(len(its))]
|
|
1005
|
+
ind = " "
|
|
1006
|
+
lines = [f"{ind}{x} = {j}" for j, x in enumerate(its)]
|
|
1007
|
+
groups: dict[str, list[str]] = {}
|
|
1008
|
+
for x, op in zip(its, ops):
|
|
1009
|
+
groups.setdefault(op, []).append(x)
|
|
1010
|
+
red = [(op, groups[op]) for op in self.OPS if op in groups]
|
|
1011
|
+
op_, cl, ii = region(self.o, self.chain(), ind, reduction=red)
|
|
1012
|
+
lines += op_ + [f"{ii}do i = 1, {n}"]
|
|
1013
|
+
for j, (x, op) in enumerate(zip(its, ops)):
|
|
1014
|
+
e = f"int(mod(i * {c[j]} + {j}, 65536), 8)"
|
|
1015
|
+
lines.append(f"{ii} {x} = " + {
|
|
1016
|
+
"+": f"{x} + {e}", "st_add": f"{x} + {e}",
|
|
1017
|
+
"max": f"max({x}, {e})", "st_max": f"max({x}, {e})",
|
|
1018
|
+
"ieor": f"ieor({x}, {e})"}[op])
|
|
1019
|
+
lines += [f"{ii}end do"] + cl
|
|
1020
|
+
lines.append(f"{ind}cs = 0")
|
|
1021
|
+
for x in its:
|
|
1022
|
+
lines.append(f"{ind}cs = mod(cs * 31 + mod({x}, {P}_8), {P}_8)")
|
|
1023
|
+
return lines
|
|
1024
|
+
|
|
1025
|
+
def value(self):
|
|
1026
|
+
n, c = self.p["n"], self.p["c"]
|
|
1027
|
+
cs = 0
|
|
1028
|
+
for j in range(self.p["nitems"]):
|
|
1029
|
+
op = self.OPS[j % 5]
|
|
1030
|
+
v = j
|
|
1031
|
+
for i in range(1, n + 1):
|
|
1032
|
+
e = (i * c[j] + j) % 65536
|
|
1033
|
+
v = v + e if op in ("+", "st_add") else max(v, e) \
|
|
1034
|
+
if op in ("max", "st_max") else v ^ e
|
|
1035
|
+
cs = (cs * 31 + v % P) % P
|
|
1036
|
+
return cs
|
|
1037
|
+
|
|
1038
|
+
def chain(self):
|
|
1039
|
+
return (("target teams distribute parallel do",),
|
|
1040
|
+
("target parallel do",),
|
|
1041
|
+
("target teams distribute parallel do",))[
|
|
1042
|
+
self.p["chain"] % 3]
|
|
1043
|
+
|
|
1044
|
+
|
|
1045
|
+
class DeclareKernel(ListKernel):
|
|
1046
|
+
"""N module variables made device resident (declare target / acc
|
|
1047
|
+
declare create) in the kernel's own module; host sets them, target
|
|
1048
|
+
update to, the region reads them all and writes w; update from."""
|
|
1049
|
+
kind = "declare"
|
|
1050
|
+
|
|
1051
|
+
def mod(self):
|
|
1052
|
+
return f"{self.name}_m"
|
|
1053
|
+
|
|
1054
|
+
def modules(self):
|
|
1055
|
+
its = self.items("v")
|
|
1056
|
+
spec = [ln.strip() for ln in pack(
|
|
1057
|
+
"integer(8) ::", [x + ("," if k < len(its) - 1 else "")
|
|
1058
|
+
for k, x in enumerate(its)], "", None,
|
|
1059
|
+
self.o.width)]
|
|
1060
|
+
spec.append(f"integer(8) :: w({self.p['n']})")
|
|
1061
|
+
if self.o.model == "omp":
|
|
1062
|
+
dl = pack("declare target(", [x + ("," if k < len(its) else ")")
|
|
1063
|
+
for k, x in enumerate(its + ["w"])],
|
|
1064
|
+
"", self.o.sent, self.o.width)
|
|
1065
|
+
else:
|
|
1066
|
+
dl = pack("declare", list_atoms("create", its + ["w"]), "",
|
|
1067
|
+
self.o.sent, self.o.width)
|
|
1068
|
+
return [Module(self.mod(), spec + dl)]
|
|
1069
|
+
|
|
1070
|
+
def uses(self):
|
|
1071
|
+
return [self.mod()]
|
|
1072
|
+
|
|
1073
|
+
def decls(self):
|
|
1074
|
+
return ["integer :: i", "integer(8) :: t"]
|
|
1075
|
+
|
|
1076
|
+
def body(self):
|
|
1077
|
+
n, c = self.p["n"], self.p["c"]
|
|
1078
|
+
its = self.items("v")
|
|
1079
|
+
ind = " "
|
|
1080
|
+
lines = [f"{ind}{x} = {c[k] * 3 + k}" for k, x in enumerate(its)]
|
|
1081
|
+
lines.append(f"{ind}w = 0")
|
|
1082
|
+
if self.o.model == "omp":
|
|
1083
|
+
lines += pack("target update", list_atoms("to", its + ["w"]),
|
|
1084
|
+
ind, self.o.sent, self.o.width)
|
|
1085
|
+
op, cl, ii = region(self.o, ("target teams distribute parallel "
|
|
1086
|
+
"do",), ind, private=["t"])
|
|
1087
|
+
else:
|
|
1088
|
+
lines += pack("update", list_atoms("device", its + ["w"]), ind,
|
|
1089
|
+
self.o.sent, self.o.width)
|
|
1090
|
+
op, cl, ii = region(self.o, ("parallel loop",), ind,
|
|
1091
|
+
private=["t"], extra=["default(present)"])
|
|
1092
|
+
lines += op + [f"{ii}do i = 1, {n}", f"{ii} t = 0"]
|
|
1093
|
+
terms = [f"{x} * mod(i, {k % 5 + 2})" for k, x in enumerate(its)]
|
|
1094
|
+
lines += sum_lines(ii + " ", "t", terms, self.o.width)
|
|
1095
|
+
lines += [f"{ii} w(i) = t", f"{ii}end do"] + cl
|
|
1096
|
+
if self.o.model == "omp":
|
|
1097
|
+
lines.append(f"{ind}{self.o.sent} target update from(w)")
|
|
1098
|
+
else:
|
|
1099
|
+
lines.append(f"{ind}{self.o.sent} update self(w)")
|
|
1100
|
+
lines.append(f"{ind}call st_cksum(w, {n}, cs)")
|
|
1101
|
+
return lines
|
|
1102
|
+
|
|
1103
|
+
def value(self):
|
|
1104
|
+
n, c = self.p["n"], self.p["c"]
|
|
1105
|
+
v = [c[k] * 3 + k for k in range(self.p["nitems"])]
|
|
1106
|
+
return cksum(sum(v[k] * (i % (k % 5 + 2)) for k in range(len(v)))
|
|
1107
|
+
for i in range(1, n + 1))
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
class SectionsKernel(ListKernel):
|
|
1111
|
+
"""Many array sections of one array: x is entered whole (enter data),
|
|
1112
|
+
then a target region maps N disjoint sections x(lo:hi) (present, so
|
|
1113
|
+
they refer to the same storage: 5.2 §5.8.3 p.155) and a target update
|
|
1114
|
+
to of a strided section x(1:m:2) (5.2 §5.9 p.164)."""
|
|
1115
|
+
kind = "sections"
|
|
1116
|
+
|
|
1117
|
+
def draw(self, rng):
|
|
1118
|
+
k = self.p.setdefault("nitems", 8)
|
|
1119
|
+
self.p.setdefault("w", 4) # elements per section
|
|
1120
|
+
self.p.setdefault("n", k * self.p["w"])
|
|
1121
|
+
self.p.setdefault("chain", 0)
|
|
1122
|
+
self.p.setdefault("c", [rng.randrange(1, 97) for _ in range(k)])
|
|
1123
|
+
|
|
1124
|
+
def decls(self):
|
|
1125
|
+
return [f"integer(8) :: x({self.p['n']})", "integer :: i"]
|
|
1126
|
+
|
|
1127
|
+
def body(self):
|
|
1128
|
+
n, w = self.p["n"], self.p["w"]
|
|
1129
|
+
k = self.p["nitems"]
|
|
1130
|
+
ind = " "
|
|
1131
|
+
secs = [f"x({j * w + 1}:{(j + 1) * w})" for j in range(k)]
|
|
1132
|
+
lines = [f"{ind}do i = 1, {n}", f"{ind} x(i) = i", f"{ind}end do"]
|
|
1133
|
+
if self.o.model == "omp":
|
|
1134
|
+
lines.append(f"{ind}{self.o.sent} target enter data map(to: x)")
|
|
1135
|
+
lines.append(f"{ind}do i = 1, {n}, 2")
|
|
1136
|
+
lines.append(f"{ind} x(i) = x(i) + 1000")
|
|
1137
|
+
lines.append(f"{ind}end do")
|
|
1138
|
+
lines.append(f"{ind}{self.o.sent} target update to(x(1:{n}:2))")
|
|
1139
|
+
op, cl, ii = region(self.o, ("target teams distribute parallel "
|
|
1140
|
+
"do",), ind,
|
|
1141
|
+
data=[(s, "tofrom") for s in secs])
|
|
1142
|
+
lines += op + [f"{ii}do i = 1, {n}",
|
|
1143
|
+
f"{ii} x(i) = x(i) * 3 + mod(i, 7)",
|
|
1144
|
+
f"{ii}end do"] + cl
|
|
1145
|
+
lines.append(f"{ind}{self.o.sent} target exit data map(from: x)")
|
|
1146
|
+
else:
|
|
1147
|
+
lines.append(f"{ind}{self.o.sent} enter data copyin(x)")
|
|
1148
|
+
lines.append(f"{ind}do i = 1, {n}, 2")
|
|
1149
|
+
lines.append(f"{ind} x(i) = x(i) + 1000")
|
|
1150
|
+
lines.append(f"{ind}end do")
|
|
1151
|
+
lines.append(f"{ind}{self.o.sent} update device(x(1:{n}:2))")
|
|
1152
|
+
op, cl, ii = region(self.o, ("parallel loop",), ind,
|
|
1153
|
+
extra=list_atoms("present", secs))
|
|
1154
|
+
lines += op + [f"{ii}do i = 1, {n}",
|
|
1155
|
+
f"{ii} x(i) = x(i) * 3 + mod(i, 7)",
|
|
1156
|
+
f"{ii}end do"] + cl
|
|
1157
|
+
lines.append(f"{ind}{self.o.sent} exit data copyout(x)")
|
|
1158
|
+
lines.append(f"{ind}call st_cksum(x, {n}, cs)")
|
|
1159
|
+
return lines
|
|
1160
|
+
|
|
1161
|
+
def value(self):
|
|
1162
|
+
n = self.p["n"]
|
|
1163
|
+
x = [i + (1000 if i % 2 == 1 else 0) for i in range(1, n + 1)]
|
|
1164
|
+
return cksum(v * 3 + (i % 7) for i, v in enumerate(x, 1))
|
|
1165
|
+
|
|
1166
|
+
def smaller(self):
|
|
1167
|
+
k = self.p["nitems"]
|
|
1168
|
+
return [self.clone(nitems=m, n=m * self.p["w"], c=self.p["c"][:m])
|
|
1169
|
+
for m in _halve(k)]
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
# --- calls, clauses, continuation lines, names --------------------------------------------------
|
|
1173
|
+
|
|
1174
|
+
def _dt_line(o: Opts, ind: str = " ") -> str:
|
|
1175
|
+
"""The device-routine marker in a procedure's specification part."""
|
|
1176
|
+
return f"{ind}{o.sent} declare target" if o.model == "omp" else \
|
|
1177
|
+
f"{ind}{o.sent} routine seq"
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
class CallsKernel(Kernel):
|
|
1181
|
+
"""A device call chain `depth` levels deep in the kernel's module:
|
|
1182
|
+
f_1(x) = f_2(mod(x*3, 1009) + 1) + 1, ..., f_D(x) = x + D; out(i) =
|
|
1183
|
+
f_1(i); optionally a RECURSIVE device function rsum(m) = m + rsum(m-1)
|
|
1184
|
+
(no specification forbids recursion in a device routine; 5.2 §7.8,
|
|
1185
|
+
OpenACC 3.4 §2.15.1)."""
|
|
1186
|
+
kind = "calls"
|
|
1187
|
+
|
|
1188
|
+
def draw(self, rng):
|
|
1189
|
+
self.p.setdefault("depth", 5)
|
|
1190
|
+
self.p.setdefault("n", 512)
|
|
1191
|
+
self.p.setdefault("recursive", rng.random() < 0.3)
|
|
1192
|
+
self.p.setdefault("rdepth", 12)
|
|
1193
|
+
|
|
1194
|
+
def fname(self, k):
|
|
1195
|
+
return f"{self.name}_f{k}"
|
|
1196
|
+
|
|
1197
|
+
def modules(self):
|
|
1198
|
+
d = self.p["depth"]
|
|
1199
|
+
cont = []
|
|
1200
|
+
for k in range(1, d + 1):
|
|
1201
|
+
cont += [f" function {self.fname(k)}(x) result(r)",
|
|
1202
|
+
_dt_line(self.o), " integer(8), intent(in) :: x",
|
|
1203
|
+
" integer(8) :: r"]
|
|
1204
|
+
if k < d:
|
|
1205
|
+
cont.append(f" r = {self.fname(k + 1)}(mod(x * 3, 1009_8) "
|
|
1206
|
+
"+ 1) + 1")
|
|
1207
|
+
else:
|
|
1208
|
+
cont.append(f" r = x + {d}")
|
|
1209
|
+
cont.append(f" end function {self.fname(k)}")
|
|
1210
|
+
if self.p["recursive"]:
|
|
1211
|
+
cont += [f" recursive function {self.name}_rs(m) result(r)",
|
|
1212
|
+
_dt_line(self.o), " integer(8), intent(in) :: m",
|
|
1213
|
+
" integer(8) :: r", " if (m <= 0) then",
|
|
1214
|
+
" r = 0", " else",
|
|
1215
|
+
f" r = m + {self.name}_rs(m - 1)", " end if",
|
|
1216
|
+
f" end function {self.name}_rs"]
|
|
1217
|
+
return [Module(f"{self.name}_m", [], cont)]
|
|
1218
|
+
|
|
1219
|
+
def uses(self):
|
|
1220
|
+
return [f"{self.name}_m"]
|
|
1221
|
+
|
|
1222
|
+
def decls(self):
|
|
1223
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i"]
|
|
1224
|
+
|
|
1225
|
+
def body(self):
|
|
1226
|
+
n = self.p["n"]
|
|
1227
|
+
ind = " "
|
|
1228
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1229
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
1230
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")])
|
|
1231
|
+
e = f"{self.fname(1)}(int(i, 8))"
|
|
1232
|
+
if self.p["recursive"]:
|
|
1233
|
+
e += f" + {self.name}_rs(int(mod(i, {self.p['rdepth']}), 8))"
|
|
1234
|
+
lines = [f"{ind}out = 0"] + op + [f"{ii}do i = 1, {n}",
|
|
1235
|
+
f"{ii} out(i) = {e}",
|
|
1236
|
+
f"{ii}end do"] + cl
|
|
1237
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1238
|
+
return lines
|
|
1239
|
+
|
|
1240
|
+
def f(self, x):
|
|
1241
|
+
d = self.p["depth"]
|
|
1242
|
+
add = 0
|
|
1243
|
+
for k in range(1, d):
|
|
1244
|
+
x = (x * 3) % 1009 + 1
|
|
1245
|
+
add += 1
|
|
1246
|
+
return x + d + add
|
|
1247
|
+
|
|
1248
|
+
def value(self):
|
|
1249
|
+
n, rd = self.p["n"], self.p["rdepth"]
|
|
1250
|
+
vals = []
|
|
1251
|
+
for i in range(1, n + 1):
|
|
1252
|
+
v = self.f(i)
|
|
1253
|
+
if self.p["recursive"]:
|
|
1254
|
+
m = i % rd
|
|
1255
|
+
v += m * (m + 1) // 2
|
|
1256
|
+
vals.append(v)
|
|
1257
|
+
return cksum(vals)
|
|
1258
|
+
|
|
1259
|
+
def smaller(self):
|
|
1260
|
+
out = [self.clone(depth=m) for m in _halve(self.p["depth"])]
|
|
1261
|
+
if self.p["recursive"]:
|
|
1262
|
+
out.append(self.clone(recursive=False))
|
|
1263
|
+
if self.p["n"] > 8:
|
|
1264
|
+
out.append(self.clone(n=8))
|
|
1265
|
+
return out
|
|
1266
|
+
|
|
1267
|
+
def features(self):
|
|
1268
|
+
f = super().features() | {f"calls:depth{self.p['depth']}"}
|
|
1269
|
+
if self.p["recursive"]:
|
|
1270
|
+
f.add("calls:recursive")
|
|
1271
|
+
return f
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
# fillable clauses of target teams distribute parallel do simd (5.0
|
|
1275
|
+
# spellings), in the order the clauses axis adds them; each: atoms,
|
|
1276
|
+
# declarations, setup (host, before), teardown (host, after)
|
|
1277
|
+
CLAUSE_ORDER = ("map", "private", "firstprivate", "reduction", "collapse",
|
|
1278
|
+
"lastprivate", "shared", "default", "defaultmap", "if",
|
|
1279
|
+
"device", "num_teams", "thread_limit", "num_threads",
|
|
1280
|
+
"dist_schedule", "schedule", "proc_bind", "safelen",
|
|
1281
|
+
"simdlen", "nontemporal", "nowait", "depend",
|
|
1282
|
+
"allocate", "uses_allocators", "in_reduction",
|
|
1283
|
+
"is_device_ptr")
|
|
1284
|
+
REPEATABLE = ("map", "private", "firstprivate", "reduction", "shared")
|
|
1285
|
+
NOT_FILLED = {
|
|
1286
|
+
"aligned": "an alignment the program cannot guarantee portably "
|
|
1287
|
+
"(a false aligned clause is unspecified behaviour)",
|
|
1288
|
+
"has_device_addr": "5.1; the program keeps 5.0 spellings for NVHPC",
|
|
1289
|
+
"linear": "on a compound with a distribute leaf only loop iteration "
|
|
1290
|
+
"variables may be linear (5.0 §2.9.4.2 p.124), and with "
|
|
1291
|
+
"collapse(2) they are lastprivate",
|
|
1292
|
+
"order": "order(concurrent) excludes safelen on the simd leaf (5.2 "
|
|
1293
|
+
"§10.4 p.235); safelen is kept",
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
|
|
1297
|
+
class ClausesKernel(Kernel):
|
|
1298
|
+
"""`size` clauses on one target teams distribute parallel do simd
|
|
1299
|
+
directive: the catalog's allowed clauses in CLAUSE_ORDER, then repeats
|
|
1300
|
+
of the repeatable ones (each repeat with its own variables). The loop
|
|
1301
|
+
is a 2-deep nest (collapse(2)); out(lin) = i*j + fp + sh."""
|
|
1302
|
+
kind = "clauses"
|
|
1303
|
+
|
|
1304
|
+
def draw(self, rng):
|
|
1305
|
+
self.p.setdefault("nclauses", 8)
|
|
1306
|
+
self.p.setdefault("ni", 16)
|
|
1307
|
+
self.p.setdefault("nj", 8)
|
|
1308
|
+
|
|
1309
|
+
def plan(self) -> list[tuple[str, int]]:
|
|
1310
|
+
from offload.engine.fuzz import allowed_clauses
|
|
1311
|
+
allowed = allowed_clauses("target teams distribute parallel do simd")
|
|
1312
|
+
base = [c for c in CLAUSE_ORDER if c in allowed]
|
|
1313
|
+
k = self.p["nclauses"]
|
|
1314
|
+
out = [(c, 0) for c in base[:k]]
|
|
1315
|
+
r = 1
|
|
1316
|
+
while len(out) < k:
|
|
1317
|
+
for c in REPEATABLE:
|
|
1318
|
+
if len(out) >= k:
|
|
1319
|
+
break
|
|
1320
|
+
out.append((c, r))
|
|
1321
|
+
r += 1
|
|
1322
|
+
return out
|
|
1323
|
+
|
|
1324
|
+
def decls(self):
|
|
1325
|
+
ni, nj = self.p["ni"], self.p["nj"]
|
|
1326
|
+
n = ni * nj
|
|
1327
|
+
d = [f"integer(8) :: out({n}), a({n})", "integer :: i, j, lin",
|
|
1328
|
+
"integer(8) :: tp, fp, rs, lp, sh, lk, ir, dd",
|
|
1329
|
+
"logical :: lt", "integer(8) :: tq"]
|
|
1330
|
+
reps = [r for c, r in self.plan() if r]
|
|
1331
|
+
for c, r in self.plan():
|
|
1332
|
+
if r:
|
|
1333
|
+
d.append(f"integer(8) :: {c[:2]}{r:04d}")
|
|
1334
|
+
if any(c == "is_device_ptr" for c, _ in self.plan()):
|
|
1335
|
+
d += ["type(c_ptr) :: cp", "integer(8), pointer :: fpp(:)",
|
|
1336
|
+
"integer(8), target :: hcopy(4)", "integer :: rc"]
|
|
1337
|
+
del reps
|
|
1338
|
+
return d
|
|
1339
|
+
|
|
1340
|
+
def uses(self):
|
|
1341
|
+
u = []
|
|
1342
|
+
if self.o.model == "omp":
|
|
1343
|
+
u.append("omp_lib")
|
|
1344
|
+
if any(c == "is_device_ptr" for c, _ in self.plan()):
|
|
1345
|
+
u.append("iso_c_binding")
|
|
1346
|
+
return u
|
|
1347
|
+
|
|
1348
|
+
def body(self):
|
|
1349
|
+
ni, nj = self.p["ni"], self.p["nj"]
|
|
1350
|
+
n = ni * nj
|
|
1351
|
+
plan = self.plan()
|
|
1352
|
+
names = [c for c, _ in plan]
|
|
1353
|
+
ind = " "
|
|
1354
|
+
lines = [f"{ind}out = 0", f"{ind}do i = 1, {n}",
|
|
1355
|
+
f"{ind} a(i) = mod(i * 13, 101)", f"{ind}end do",
|
|
1356
|
+
f"{ind}fp = 7", f"{ind}sh = 5", f"{ind}rs = 0",
|
|
1357
|
+
f"{ind}lp = 0", f"{ind}lk = 0", f"{ind}ir = 0",
|
|
1358
|
+
f"{ind}dd = 0", f"{ind}lt = .true.", f"{ind}tq = 0"]
|
|
1359
|
+
for c, r in plan:
|
|
1360
|
+
if r:
|
|
1361
|
+
v = f"{c[:2]}{r:04d}"
|
|
1362
|
+
lines.append(f"{ind}{v} = {r}")
|
|
1363
|
+
atoms = []
|
|
1364
|
+
body_extra = []
|
|
1365
|
+
after = []
|
|
1366
|
+
for c, r in plan:
|
|
1367
|
+
v = f"{c[:2]}{r:04d}" if r else ""
|
|
1368
|
+
if c == "map":
|
|
1369
|
+
atoms += (["map(to: a)", "map(tofrom: out)"] if not r
|
|
1370
|
+
else [f"map(tofrom: {v})"])
|
|
1371
|
+
elif c == "private":
|
|
1372
|
+
# lin (the linear index each iteration computes) is private
|
|
1373
|
+
# with the first private clause (fix, F1:
|
|
1374
|
+
# it was shared, a data race in every clauses program)
|
|
1375
|
+
atoms.append(f"private({v})" if r else "private(tp, lin)")
|
|
1376
|
+
body_extra.append(f"{v or 'tp'} = i")
|
|
1377
|
+
elif c == "firstprivate":
|
|
1378
|
+
atoms.append(f"firstprivate({v or 'fp'})")
|
|
1379
|
+
elif c == "reduction":
|
|
1380
|
+
atoms.append(f"reduction(+: {v or 'rs'})")
|
|
1381
|
+
body_extra.append(f"{v or 'rs'} = {v or 'rs'} + 1")
|
|
1382
|
+
if r:
|
|
1383
|
+
after.append(v)
|
|
1384
|
+
elif c == "collapse":
|
|
1385
|
+
atoms.append("collapse(2)")
|
|
1386
|
+
elif c == "lastprivate":
|
|
1387
|
+
atoms.append("lastprivate(lp)")
|
|
1388
|
+
body_extra.append("lp = lin")
|
|
1389
|
+
elif c == "shared":
|
|
1390
|
+
atoms.append(f"shared({v or 'sh'})")
|
|
1391
|
+
elif c == "default":
|
|
1392
|
+
atoms.append("default(shared)")
|
|
1393
|
+
elif c == "defaultmap":
|
|
1394
|
+
atoms.append("defaultmap(tofrom: scalar)")
|
|
1395
|
+
elif c == "if":
|
|
1396
|
+
atoms += ["if(target: lt)", "if(parallel: lt)"]
|
|
1397
|
+
elif c == "device":
|
|
1398
|
+
atoms.append("device(omp_get_default_device())")
|
|
1399
|
+
elif c == "num_teams":
|
|
1400
|
+
atoms.append("num_teams(4)")
|
|
1401
|
+
elif c == "thread_limit":
|
|
1402
|
+
atoms.append("thread_limit(64)")
|
|
1403
|
+
elif c == "num_threads":
|
|
1404
|
+
atoms.append("num_threads(32)")
|
|
1405
|
+
elif c == "dist_schedule":
|
|
1406
|
+
atoms.append("dist_schedule(static, 4)")
|
|
1407
|
+
elif c == "schedule":
|
|
1408
|
+
atoms.append("schedule(static, 2)")
|
|
1409
|
+
elif c == "proc_bind":
|
|
1410
|
+
atoms.append("proc_bind(close)")
|
|
1411
|
+
elif c == "safelen":
|
|
1412
|
+
atoms.append("safelen(8)")
|
|
1413
|
+
elif c == "simdlen":
|
|
1414
|
+
atoms.append("simdlen(4)")
|
|
1415
|
+
elif c == "nontemporal":
|
|
1416
|
+
atoms.append("nontemporal(a)")
|
|
1417
|
+
elif c == "order":
|
|
1418
|
+
atoms.append("order(concurrent)")
|
|
1419
|
+
elif c == "nowait":
|
|
1420
|
+
atoms.append("nowait")
|
|
1421
|
+
elif c == "depend":
|
|
1422
|
+
atoms.append("depend(inout: dd)")
|
|
1423
|
+
elif c == "linear":
|
|
1424
|
+
atoms.append("linear(lk: 1)")
|
|
1425
|
+
elif c == "allocate":
|
|
1426
|
+
atoms.append("allocate(omp_default_mem_alloc: tp)")
|
|
1427
|
+
elif c == "uses_allocators":
|
|
1428
|
+
atoms.append("uses_allocators(omp_default_mem_alloc)")
|
|
1429
|
+
elif c == "in_reduction":
|
|
1430
|
+
atoms.append("in_reduction(+: ir)")
|
|
1431
|
+
body_extra.append("if (lin == 1) ir = ir + 5")
|
|
1432
|
+
elif c == "is_device_ptr":
|
|
1433
|
+
atoms.append("is_device_ptr(cp)")
|
|
1434
|
+
if "private" not in names:
|
|
1435
|
+
# lin must be private even when the private clause is not one of
|
|
1436
|
+
# the clauses drawn (an extra clause, not counted)
|
|
1437
|
+
atoms.append("private(lin)")
|
|
1438
|
+
if "allocate" in names and not any(x.startswith("private(tp")
|
|
1439
|
+
for x in atoms):
|
|
1440
|
+
atoms.append("private(tp)")
|
|
1441
|
+
body_extra.append("tp = i")
|
|
1442
|
+
pre, post = [], []
|
|
1443
|
+
if "is_device_ptr" in names:
|
|
1444
|
+
pre += [f"{ind}cp = omp_target_alloc(int(4 * 8, c_size_t), "
|
|
1445
|
+
"omp_get_default_device())"]
|
|
1446
|
+
body_extra.append("if (lin == 1) then")
|
|
1447
|
+
body_extra.append(" call c_f_pointer(cp, fpp, [4])")
|
|
1448
|
+
body_extra.append(" fpp(1) = 11")
|
|
1449
|
+
body_extra.append(" fpp(2) = 22")
|
|
1450
|
+
body_extra.append(" fpp(3) = 33")
|
|
1451
|
+
body_extra.append(" fpp(4) = 44")
|
|
1452
|
+
body_extra.append("end if")
|
|
1453
|
+
post += pack("rc = omp_target_memcpy(", [
|
|
1454
|
+
"c_loc(hcopy),", "cp,", "int(4 * 8, c_size_t),",
|
|
1455
|
+
"0_c_size_t,", "0_c_size_t,", "omp_get_initial_device(),",
|
|
1456
|
+
"omp_get_default_device())"], ind, None, self.o.width) + [
|
|
1457
|
+
f"{ind}call omp_target_free(cp, "
|
|
1458
|
+
"omp_get_default_device())"]
|
|
1459
|
+
if "in_reduction" in names:
|
|
1460
|
+
pre.append(f"{ind}{self.o.sent} taskgroup task_reduction(+: ir)")
|
|
1461
|
+
post.insert(0, f"{ind}{self.o.sent} end taskgroup")
|
|
1462
|
+
lines += pre
|
|
1463
|
+
dname = "target teams distribute parallel do simd"
|
|
1464
|
+
lines += pack(dname, atoms, ind, self.o.sent, self.o.width)
|
|
1465
|
+
lines += [f"{ind}do i = 1, {ni}", f"{ind} do j = 1, {nj}",
|
|
1466
|
+
f"{ind} lin = (i - 1) * {nj} + j"]
|
|
1467
|
+
lines += [f"{ind} {s}" for s in body_extra]
|
|
1468
|
+
lines += [f"{ind} out(lin) = i * j + fp + sh + a(lin)",
|
|
1469
|
+
f"{ind} end do", f"{ind}end do",
|
|
1470
|
+
f"{ind}{self.o.sent} end {dname}"]
|
|
1471
|
+
if "nowait" in names or "depend" in names:
|
|
1472
|
+
lines.append(f"{ind}{self.o.sent} taskwait")
|
|
1473
|
+
lines += post
|
|
1474
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1475
|
+
if "reduction" in names:
|
|
1476
|
+
lines.append(f"{ind}cs = mod(cs + rs, {P}_8)")
|
|
1477
|
+
for v in after:
|
|
1478
|
+
lines.append(f"{ind}cs = mod(cs + {v}, {P}_8)")
|
|
1479
|
+
if "lastprivate" in names:
|
|
1480
|
+
lines.append(f"{ind}cs = mod(cs + lp, {P}_8)")
|
|
1481
|
+
if "in_reduction" in names:
|
|
1482
|
+
lines.append(f"{ind}cs = mod(cs + ir, {P}_8)")
|
|
1483
|
+
if "is_device_ptr" in names:
|
|
1484
|
+
lines.append(f"{ind}cs = mod(cs + hcopy(1) + hcopy(2) + "
|
|
1485
|
+
f"hcopy(3) + hcopy(4), {P}_8)")
|
|
1486
|
+
return lines
|
|
1487
|
+
|
|
1488
|
+
def value(self):
|
|
1489
|
+
ni, nj = self.p["ni"], self.p["nj"]
|
|
1490
|
+
n = ni * nj
|
|
1491
|
+
plan = self.plan()
|
|
1492
|
+
names = [c for c, _ in plan]
|
|
1493
|
+
out = []
|
|
1494
|
+
for i in range(1, ni + 1):
|
|
1495
|
+
for j in range(1, nj + 1):
|
|
1496
|
+
lin = (i - 1) * nj + j
|
|
1497
|
+
out.append(i * j + 7 + 5 + (lin * 13) % 101)
|
|
1498
|
+
cs = cksum(out)
|
|
1499
|
+
if "reduction" in names:
|
|
1500
|
+
cs = (cs + n) % P
|
|
1501
|
+
for c, r in plan:
|
|
1502
|
+
if r and c == "reduction":
|
|
1503
|
+
cs = (cs + r + n) % P
|
|
1504
|
+
if "lastprivate" in names:
|
|
1505
|
+
cs = (cs + n) % P
|
|
1506
|
+
if "in_reduction" in names:
|
|
1507
|
+
cs = (cs + 5) % P
|
|
1508
|
+
if "is_device_ptr" in names:
|
|
1509
|
+
cs = (cs + 110) % P
|
|
1510
|
+
return cs
|
|
1511
|
+
|
|
1512
|
+
def smaller(self):
|
|
1513
|
+
k = self.p["nclauses"]
|
|
1514
|
+
return [self.clone(nclauses=m) for m in _halve(k)] + \
|
|
1515
|
+
([self.clone(nclauses=k - 1)] if k > 2 else [])
|
|
1516
|
+
|
|
1517
|
+
def features(self):
|
|
1518
|
+
return super().features() | {f"clause:{c}" for c, _ in self.plan()} \
|
|
1519
|
+
| {f"len:clauses:{self.p['nclauses']}"}
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
class ContKernel(PrivateKernel):
|
|
1523
|
+
"""One directive spanning `nitems` continuation lines: the private list
|
|
1524
|
+
one item per line (PrivateKernel's program with width 1 for the
|
|
1525
|
+
directive)."""
|
|
1526
|
+
kind = "contlines"
|
|
1527
|
+
|
|
1528
|
+
def body(self):
|
|
1529
|
+
o = self.o
|
|
1530
|
+
saved = o.width
|
|
1531
|
+
try:
|
|
1532
|
+
self.o = Opts(o.model, o.spell, o.level, width=1)
|
|
1533
|
+
lines = super().body()
|
|
1534
|
+
finally:
|
|
1535
|
+
self.o = Opts(o.model, o.spell, o.level, width=saved)
|
|
1536
|
+
return lines
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
def long_name(prefix: str, k: int, length: int) -> str:
|
|
1540
|
+
base = f"{prefix}{k}_"
|
|
1541
|
+
return (base + "x" * max(0, length - len(base)))[:max(length, len(base))]
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
class NamesKernel(Kernel):
|
|
1545
|
+
"""Names of exactly `length` characters: the kernel's module, a device
|
|
1546
|
+
function, a derived type and its component, and `count` variables in a
|
|
1547
|
+
private list (63 is the Fortran limit; longer: an illegal probe)."""
|
|
1548
|
+
kind = "names"
|
|
1549
|
+
|
|
1550
|
+
def draw(self, rng):
|
|
1551
|
+
self.p.setdefault("length", 63)
|
|
1552
|
+
self.p.setdefault("count", 4)
|
|
1553
|
+
self.p.setdefault("n", 64)
|
|
1554
|
+
|
|
1555
|
+
def nm(self, tag, k=0):
|
|
1556
|
+
return long_name(f"{tag}{self.name[1:]}", k, self.p["length"])
|
|
1557
|
+
|
|
1558
|
+
def modules(self):
|
|
1559
|
+
L = self.p["length"]
|
|
1560
|
+
t, c, f = self.nm("t"), self.nm("c"), self.nm("f")
|
|
1561
|
+
spec = [f"type :: {t}", f" integer(8) :: {c}", f"end type {t}"]
|
|
1562
|
+
cont = [f" function {f}(x) result(r)", _dt_line(self.o),
|
|
1563
|
+
" integer(8), intent(in) :: x", " integer(8) :: r",
|
|
1564
|
+
" r = x * 3 + 1", f" end function {f}"]
|
|
1565
|
+
del L
|
|
1566
|
+
return [Module(self.nm("m"), spec, cont)]
|
|
1567
|
+
|
|
1568
|
+
def uses(self):
|
|
1569
|
+
return [self.nm("m")]
|
|
1570
|
+
|
|
1571
|
+
def decls(self):
|
|
1572
|
+
n = self.p["n"]
|
|
1573
|
+
vs = [self.nm("v", k) for k in range(self.p["count"])]
|
|
1574
|
+
return [f"integer(8) :: out({n})", "integer :: i",
|
|
1575
|
+
f"type({self.nm('t')}) :: obj"] + \
|
|
1576
|
+
[f"integer(8) :: {v}" for v in vs]
|
|
1577
|
+
|
|
1578
|
+
def body(self):
|
|
1579
|
+
n = self.p["n"]
|
|
1580
|
+
vs = [self.nm("v", k) for k in range(self.p["count"])]
|
|
1581
|
+
ind = " "
|
|
1582
|
+
f, c = self.nm("f"), self.nm("c")
|
|
1583
|
+
lines = [f"{ind}out = 0", f"{ind}obj%{c} = 9"]
|
|
1584
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1585
|
+
self.o.model == "omp" else ("parallel loop",)
|
|
1586
|
+
op, cl, ii = region(self.o, chain, ind,
|
|
1587
|
+
data=[("out", "tofrom"), ("obj", "to")],
|
|
1588
|
+
private=vs)
|
|
1589
|
+
lines += op + [f"{ii}do i = 1, {n}"]
|
|
1590
|
+
for k, v in enumerate(vs):
|
|
1591
|
+
lines += pack(f"{v} =", [f"{f}(int(i, 8))", f"+ {k}"],
|
|
1592
|
+
ii + " ", None, self.o.width)
|
|
1593
|
+
lines += sum_lines(ii + " ", "out(i)", vs + [f"obj%{c}"],
|
|
1594
|
+
self.o.width)
|
|
1595
|
+
lines += [f"{ii}end do"] + cl
|
|
1596
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1597
|
+
return lines
|
|
1598
|
+
|
|
1599
|
+
def value(self):
|
|
1600
|
+
n, cnt = self.p["n"], self.p["count"]
|
|
1601
|
+
return cksum(sum(i * 3 + 1 + k for k in range(cnt)) + 9
|
|
1602
|
+
for i in range(1, n + 1))
|
|
1603
|
+
|
|
1604
|
+
def smaller(self):
|
|
1605
|
+
out = []
|
|
1606
|
+
if self.p["count"] > 1:
|
|
1607
|
+
out.append(self.clone(count=1))
|
|
1608
|
+
if self.p["length"] > 63:
|
|
1609
|
+
out.append(self.clone(length=64))
|
|
1610
|
+
return out
|
|
1611
|
+
|
|
1612
|
+
def features(self):
|
|
1613
|
+
return super().features() | {f"len:names:{self.p['length']}"}
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
# --- long variable lists ---------------------------------------------------------------------------
|
|
1617
|
+
|
|
1618
|
+
def decl_lines(typ: str, names: list[str], width: int) -> list[str]:
|
|
1619
|
+
return [ln.strip() for ln in pack(f"{typ} ::", [
|
|
1620
|
+
x + ("," if k < len(names) - 1 else "")
|
|
1621
|
+
for k, x in enumerate(names)], "", None, width)]
|
|
1622
|
+
|
|
1623
|
+
|
|
1624
|
+
class LocalsKernel(Kernel):
|
|
1625
|
+
"""A device routine with `nlocals` local variables (scalars and, every
|
|
1626
|
+
eighth, a 4-element array): res = sum of q_j = mod(x*(j+1)+j, 991)."""
|
|
1627
|
+
kind = "locals"
|
|
1628
|
+
|
|
1629
|
+
def draw(self, rng):
|
|
1630
|
+
self.p.setdefault("nlocals", 64)
|
|
1631
|
+
self.p.setdefault("n", max(8, min(256, 100000 // max(
|
|
1632
|
+
1, self.p["nlocals"]))))
|
|
1633
|
+
|
|
1634
|
+
def modules(self):
|
|
1635
|
+
k = self.p["nlocals"]
|
|
1636
|
+
sc = [vname("q", j) for j in range(1, k + 1) if j % 8]
|
|
1637
|
+
ar = [vname("q", j) for j in range(1, k + 1) if not j % 8]
|
|
1638
|
+
cont = [f" subroutine {self.name}_dr(x, res)", _dt_line(self.o),
|
|
1639
|
+
" integer(8), intent(in) :: x",
|
|
1640
|
+
" integer(8), intent(out) :: res"]
|
|
1641
|
+
cont += [" " + d for d in decl_lines("integer(8)", sc,
|
|
1642
|
+
self.o.width)]
|
|
1643
|
+
if ar:
|
|
1644
|
+
cont += [" " + d for d in decl_lines(
|
|
1645
|
+
"integer(8)", [f"{a}(4)" for a in ar], self.o.width)]
|
|
1646
|
+
for j in range(1, k + 1):
|
|
1647
|
+
v = vname("q", j)
|
|
1648
|
+
rhs = f"mod(x * {j + 1} + {j}, 991_8)"
|
|
1649
|
+
cont.append(f" {v} = {rhs}" if j % 8 else f" {v} = {rhs}")
|
|
1650
|
+
cont.append(" res = 0")
|
|
1651
|
+
terms = [vname("q", j) if j % 8 else f"{vname('q', j)}(3)"
|
|
1652
|
+
for j in range(1, k + 1)]
|
|
1653
|
+
cont += sum_lines(" ", "res", terms, self.o.width)
|
|
1654
|
+
cont.append(f" end subroutine {self.name}_dr")
|
|
1655
|
+
return [Module(f"{self.name}_m", [], cont)]
|
|
1656
|
+
|
|
1657
|
+
def uses(self):
|
|
1658
|
+
return [f"{self.name}_m"]
|
|
1659
|
+
|
|
1660
|
+
def decls(self):
|
|
1661
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i",
|
|
1662
|
+
"integer(8) :: r"]
|
|
1663
|
+
|
|
1664
|
+
def body(self):
|
|
1665
|
+
n = self.p["n"]
|
|
1666
|
+
ind = " "
|
|
1667
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1668
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
1669
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")],
|
|
1670
|
+
private=["r"])
|
|
1671
|
+
return [f"{ind}out = 0"] + op + [
|
|
1672
|
+
f"{ii}do i = 1, {n}",
|
|
1673
|
+
f"{ii} call {self.name}_dr(int(i, 8), r)",
|
|
1674
|
+
f"{ii} out(i) = r", f"{ii}end do"] + cl + [
|
|
1675
|
+
f"{ind}call st_cksum(out, {n}, cs)"]
|
|
1676
|
+
|
|
1677
|
+
def value(self):
|
|
1678
|
+
k, n = self.p["nlocals"], self.p["n"]
|
|
1679
|
+
return cksum(sum((i * (j + 1) + j) % 991 for j in range(1, k + 1))
|
|
1680
|
+
for i in range(1, n + 1))
|
|
1681
|
+
|
|
1682
|
+
def smaller(self):
|
|
1683
|
+
return [self.clone(nlocals=m) for m in _halve(self.p["nlocals"])] \
|
|
1684
|
+
+ ([self.clone(n=8)] if self.p["n"] > 8 else [])
|
|
1685
|
+
|
|
1686
|
+
def features(self):
|
|
1687
|
+
return super().features() | {f"len:locals:{self.p['nlocals']}"}
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
ARG_KINDS = ("value", "ref", "array", "derived", "optional")
|
|
1691
|
+
|
|
1692
|
+
|
|
1693
|
+
class ArgsKernel(Kernel):
|
|
1694
|
+
"""A device routine with `nargs` dummy arguments, kinds cycling through
|
|
1695
|
+
VALUE scalar, by-reference scalar, explicit-shape array(4), a derived
|
|
1696
|
+
type, and (last) OPTIONAL scalars of which every other one is passed
|
|
1697
|
+
(by keyword after the first omitted one)."""
|
|
1698
|
+
kind = "args"
|
|
1699
|
+
|
|
1700
|
+
def draw(self, rng):
|
|
1701
|
+
self.p.setdefault("nargs", 16)
|
|
1702
|
+
self.p.setdefault("n", max(8, min(256, 60000 // max(
|
|
1703
|
+
1, self.p["nargs"]))))
|
|
1704
|
+
|
|
1705
|
+
def kinds(self):
|
|
1706
|
+
k = self.p["nargs"]
|
|
1707
|
+
nopt = max(0, k // 5)
|
|
1708
|
+
req = [ARG_KINDS[j % 4] for j in range(k - nopt)]
|
|
1709
|
+
return req + ["optional"] * nopt
|
|
1710
|
+
|
|
1711
|
+
def modules(self):
|
|
1712
|
+
ks = self.kinds()
|
|
1713
|
+
names = [vname("a", j) for j in range(1, len(ks) + 1)]
|
|
1714
|
+
spec = ["type :: st_pairT", " integer(8) :: u, v", "end type"] \
|
|
1715
|
+
if False else []
|
|
1716
|
+
cont = []
|
|
1717
|
+
cont += pack(f"subroutine {self.name}_dr(", [
|
|
1718
|
+
x + ("," if j < len(names) else ")") for j, x in
|
|
1719
|
+
enumerate(names + ["res"])], " ", None, self.o.width)
|
|
1720
|
+
cont.append(_dt_line(self.o))
|
|
1721
|
+
# declarations grouped by kind
|
|
1722
|
+
groups: dict[str, list[str]] = {}
|
|
1723
|
+
for x, kd in zip(names, ks):
|
|
1724
|
+
groups.setdefault(kd, []).append(x)
|
|
1725
|
+
typ = {"value": "integer(8), value", "ref": "integer(8), intent(in)",
|
|
1726
|
+
"array": "integer(8), intent(in)",
|
|
1727
|
+
"derived": "type(st_pair), intent(in)",
|
|
1728
|
+
"optional": "integer(8), intent(in), optional"}
|
|
1729
|
+
for kd in ARG_KINDS:
|
|
1730
|
+
if kd in groups:
|
|
1731
|
+
ents = [f"{x}(4)" if kd == "array" else x
|
|
1732
|
+
for x in groups[kd]]
|
|
1733
|
+
cont += [" " + d for d in decl_lines(typ[kd], ents,
|
|
1734
|
+
self.o.width)]
|
|
1735
|
+
cont.append(" integer(8), intent(out) :: res")
|
|
1736
|
+
cont.append(" res = 0")
|
|
1737
|
+
for j, (x, kd) in enumerate(zip(names, ks), 1):
|
|
1738
|
+
if kd in ("value", "ref"):
|
|
1739
|
+
cont.append(f" res = res + {x} * {j % 13 + 1}")
|
|
1740
|
+
elif kd == "array":
|
|
1741
|
+
cont.append(f" res = res + {x}(1) + {x}(4) * 2")
|
|
1742
|
+
elif kd == "derived":
|
|
1743
|
+
cont.append(f" res = res + {x}%u * 3 + {x}%v")
|
|
1744
|
+
else:
|
|
1745
|
+
cont.append(f" if (present({x})) res = res + {x} * 5")
|
|
1746
|
+
cont.append(f" end subroutine {self.name}_dr")
|
|
1747
|
+
return [Module(f"{self.name}_m", spec, cont, ["st_util"])]
|
|
1748
|
+
|
|
1749
|
+
def uses(self):
|
|
1750
|
+
return [f"{self.name}_m", "st_util"]
|
|
1751
|
+
|
|
1752
|
+
def decls(self):
|
|
1753
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i",
|
|
1754
|
+
"integer(8) :: r, s", "integer(8) :: arr(4)",
|
|
1755
|
+
"type(st_pair) :: pr"]
|
|
1756
|
+
|
|
1757
|
+
def actuals(self):
|
|
1758
|
+
ks = self.kinds()
|
|
1759
|
+
acts, keyword = [], False
|
|
1760
|
+
for j, kd in enumerate(ks, 1):
|
|
1761
|
+
x = vname("a", j)
|
|
1762
|
+
if kd in ("value", "ref"):
|
|
1763
|
+
acts.append(f"s + {j}" if kd == "value" else "s")
|
|
1764
|
+
elif kd == "array":
|
|
1765
|
+
acts.append("arr")
|
|
1766
|
+
elif kd == "derived":
|
|
1767
|
+
acts.append("pr")
|
|
1768
|
+
else:
|
|
1769
|
+
if j % 2:
|
|
1770
|
+
acts.append(f"{x}=s" if keyword else "s")
|
|
1771
|
+
else:
|
|
1772
|
+
keyword = True
|
|
1773
|
+
acts.append("res=r" if keyword else "r")
|
|
1774
|
+
return acts
|
|
1775
|
+
|
|
1776
|
+
def body(self):
|
|
1777
|
+
n = self.p["n"]
|
|
1778
|
+
ind = " "
|
|
1779
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1780
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
1781
|
+
op, cl, ii = region(self.o, chain, ind,
|
|
1782
|
+
data=[("out", "tofrom"), ("arr", "to"),
|
|
1783
|
+
("pr", "to")], private=["r", "s"])
|
|
1784
|
+
lines = [f"{ind}out = 0", f"{ind}arr = [3, 5, 7, 11]",
|
|
1785
|
+
f"{ind}pr%u = 4", f"{ind}pr%v = 9"]
|
|
1786
|
+
lines += op + [f"{ii}do i = 1, {n}", f"{ii} s = i"]
|
|
1787
|
+
lines += call_lines(ii + " ", f"{self.name}_dr", self.actuals(),
|
|
1788
|
+
self.o.width)
|
|
1789
|
+
lines += [f"{ii} out(i) = r", f"{ii}end do"] + cl
|
|
1790
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1791
|
+
return lines
|
|
1792
|
+
|
|
1793
|
+
def value(self):
|
|
1794
|
+
ks, n = self.kinds(), self.p["n"]
|
|
1795
|
+
vals = []
|
|
1796
|
+
for i in range(1, n + 1):
|
|
1797
|
+
res = 0
|
|
1798
|
+
for j, kd in enumerate(ks, 1):
|
|
1799
|
+
if kd == "value":
|
|
1800
|
+
res += (i + j) * (j % 13 + 1)
|
|
1801
|
+
elif kd == "ref":
|
|
1802
|
+
res += i * (j % 13 + 1)
|
|
1803
|
+
elif kd == "array":
|
|
1804
|
+
res += 3 + 11 * 2
|
|
1805
|
+
elif kd == "derived":
|
|
1806
|
+
res += 4 * 3 + 9
|
|
1807
|
+
elif j % 2:
|
|
1808
|
+
res += i * 5
|
|
1809
|
+
vals.append(res)
|
|
1810
|
+
return cksum(vals)
|
|
1811
|
+
|
|
1812
|
+
def smaller(self):
|
|
1813
|
+
return [self.clone(nargs=m) for m in _halve(self.p["nargs"])] + \
|
|
1814
|
+
([self.clone(n=8)] if self.p["n"] > 8 else [])
|
|
1815
|
+
|
|
1816
|
+
def features(self):
|
|
1817
|
+
return super().features() | {f"len:args:{self.p['nargs']}"} | {
|
|
1818
|
+
f"args:{k}" for k in set(self.kinds())}
|
|
1819
|
+
|
|
1820
|
+
|
|
1821
|
+
class UseOnlyKernel(Kernel):
|
|
1822
|
+
"""`use <module>, only: ...` with `nitems` names: half named constants
|
|
1823
|
+
(parameters), half device-resident module variables."""
|
|
1824
|
+
kind = "useonly"
|
|
1825
|
+
|
|
1826
|
+
def draw(self, rng):
|
|
1827
|
+
self.p.setdefault("nitems", 16)
|
|
1828
|
+
self.p.setdefault("n", max(8, min(256, 100000 // max(
|
|
1829
|
+
1, self.p["nitems"]))))
|
|
1830
|
+
|
|
1831
|
+
def names(self):
|
|
1832
|
+
k = self.p["nitems"]
|
|
1833
|
+
return [vname("u", j) for j in range(1, k + 1)]
|
|
1834
|
+
|
|
1835
|
+
def modules(self):
|
|
1836
|
+
nm = self.names()
|
|
1837
|
+
spec = []
|
|
1838
|
+
pv = [x for j, x in enumerate(nm) if j % 2 == 0]
|
|
1839
|
+
dv = [x for j, x in enumerate(nm) if j % 2 == 1]
|
|
1840
|
+
for j, x in enumerate(nm):
|
|
1841
|
+
if j % 2 == 0:
|
|
1842
|
+
spec.append(f"integer(8), parameter :: {x} = {j * 3 + 1}")
|
|
1843
|
+
if dv:
|
|
1844
|
+
spec += decl_lines("integer(8)", dv, self.o.width)
|
|
1845
|
+
if self.o.model == "omp":
|
|
1846
|
+
spec += pack("declare target(", [
|
|
1847
|
+
x + ("," if k < len(dv) - 1 else ")")
|
|
1848
|
+
for k, x in enumerate(dv)], "", self.o.sent,
|
|
1849
|
+
self.o.width)
|
|
1850
|
+
else:
|
|
1851
|
+
spec += pack("declare", list_atoms("create", dv), "",
|
|
1852
|
+
self.o.sent, self.o.width)
|
|
1853
|
+
del pv
|
|
1854
|
+
# a decoy name the kernel does not import
|
|
1855
|
+
spec.append(f"integer(8) :: {self.name}_unused")
|
|
1856
|
+
return [Module(f"{self.name}_m", spec)]
|
|
1857
|
+
|
|
1858
|
+
def routine(self):
|
|
1859
|
+
lines = super().routine()
|
|
1860
|
+
nm = self.names()
|
|
1861
|
+
use = pack(f"use {self.name}_m, only:", [
|
|
1862
|
+
x + ("," if k < len(nm) - 1 else "")
|
|
1863
|
+
for k, x in enumerate(nm)], " ", None, self.o.width)
|
|
1864
|
+
return [lines[0]] + use + lines[1:]
|
|
1865
|
+
|
|
1866
|
+
def decls(self):
|
|
1867
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i",
|
|
1868
|
+
"integer(8) :: t"]
|
|
1869
|
+
|
|
1870
|
+
def body(self):
|
|
1871
|
+
n = self.p["n"]
|
|
1872
|
+
nm = self.names()
|
|
1873
|
+
dv = [x for j, x in enumerate(nm) if j % 2 == 1]
|
|
1874
|
+
ind = " "
|
|
1875
|
+
lines = [f"{ind}{x} = {j * 3 + 1}" for j, x in enumerate(nm)
|
|
1876
|
+
if j % 2 == 1]
|
|
1877
|
+
if dv:
|
|
1878
|
+
if self.o.model == "omp":
|
|
1879
|
+
lines += pack("target update", list_atoms("to", dv), ind,
|
|
1880
|
+
self.o.sent, self.o.width)
|
|
1881
|
+
else:
|
|
1882
|
+
lines += pack("update", list_atoms("device", dv), ind,
|
|
1883
|
+
self.o.sent, self.o.width)
|
|
1884
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1885
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
1886
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")],
|
|
1887
|
+
private=["t"])
|
|
1888
|
+
lines += [f"{ind}out = 0"] + op + [f"{ii}do i = 1, {n}",
|
|
1889
|
+
f"{ii} t = i"]
|
|
1890
|
+
lines += sum_lines(ii + " ", "t", nm, self.o.width)
|
|
1891
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do"] + cl
|
|
1892
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1893
|
+
return lines
|
|
1894
|
+
|
|
1895
|
+
def value(self):
|
|
1896
|
+
k, n = self.p["nitems"], self.p["n"]
|
|
1897
|
+
s = sum(j * 3 + 1 for j in range(k))
|
|
1898
|
+
return cksum(i + s for i in range(1, n + 1))
|
|
1899
|
+
|
|
1900
|
+
def smaller(self):
|
|
1901
|
+
return [self.clone(nitems=m) for m in _halve(self.p["nitems"])]
|
|
1902
|
+
|
|
1903
|
+
def features(self):
|
|
1904
|
+
return super().features() | {f"len:useonly:{self.p['nitems']}"}
|
|
1905
|
+
|
|
1906
|
+
|
|
1907
|
+
class CaptureKernel(ListKernel):
|
|
1908
|
+
"""`nitems` host scalars referenced in the region with no clause
|
|
1909
|
+
(implicitly firstprivate: OpenMP 5.2 §5.8.1 p.148; OpenACC 3.4 §2.6.2
|
|
1910
|
+
p.41 for parallel)."""
|
|
1911
|
+
kind = "capture"
|
|
1912
|
+
|
|
1913
|
+
def decls(self):
|
|
1914
|
+
n = self.p["n"]
|
|
1915
|
+
its = self.items("s")
|
|
1916
|
+
return [f"integer(8) :: out({n})", "integer :: i", "integer(8) :: t"] \
|
|
1917
|
+
+ decl_lines("integer(8)", its, self.o.width)
|
|
1918
|
+
|
|
1919
|
+
def body(self):
|
|
1920
|
+
n, c = self.p["n"], self.p["c"]
|
|
1921
|
+
its = self.items("s")
|
|
1922
|
+
ind = " "
|
|
1923
|
+
lines = [f"{ind}{x} = {c[k] + 2 * k}" for k, x in enumerate(its)]
|
|
1924
|
+
lines.append(f"{ind}out = 0")
|
|
1925
|
+
chain = ("target teams distribute parallel do",) if \
|
|
1926
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
1927
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")],
|
|
1928
|
+
private=["t"])
|
|
1929
|
+
lines += op + [f"{ii}do i = 1, {n}", f"{ii} t = i"]
|
|
1930
|
+
terms = [f"{x} * mod(i, {k % 3 + 2})" for k, x in enumerate(its)]
|
|
1931
|
+
lines += sum_lines(ii + " ", "t", terms, self.o.width)
|
|
1932
|
+
lines += [f"{ii} out(i) = t", f"{ii}end do"] + cl
|
|
1933
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
1934
|
+
return lines
|
|
1935
|
+
|
|
1936
|
+
def value(self):
|
|
1937
|
+
n, c = self.p["n"], self.p["c"]
|
|
1938
|
+
k = self.p["nitems"]
|
|
1939
|
+
s = [c[j] + 2 * j for j in range(k)]
|
|
1940
|
+
return cksum(i + sum(s[j] * (i % (j % 3 + 2)) for j in range(k))
|
|
1941
|
+
for i in range(1, n + 1))
|
|
1942
|
+
|
|
1943
|
+
|
|
1944
|
+
# --- nested derived types and classes ------------------------------------------------------------
|
|
1945
|
+
|
|
1946
|
+
class DTNestKernel(Kernel):
|
|
1947
|
+
"""Derived types nested `depth` levels (t1 contains t2 ... contains tD),
|
|
1948
|
+
each level with a scalar s and an allocatable component v(:) (and, with
|
|
1949
|
+
ptr, a pointer component at the deepest level); an array x(na) of t1;
|
|
1950
|
+
deep copy by enter data of x then of every x(e)%c...%v (OpenMP 5.2
|
|
1951
|
+
§5.8.3: a list item and its containing structure may both be mapped),
|
|
1952
|
+
or one region mapping them all (mode 'region'); out(i) = sum over
|
|
1953
|
+
elements and levels of v(i) + s."""
|
|
1954
|
+
kind = "dtnest"
|
|
1955
|
+
|
|
1956
|
+
def draw(self, rng):
|
|
1957
|
+
self.p.setdefault("depth", 3)
|
|
1958
|
+
self.p.setdefault("na", 2)
|
|
1959
|
+
self.p.setdefault("m", 16)
|
|
1960
|
+
self.p.setdefault("mode", rng.choice(("enter", "region")))
|
|
1961
|
+
self.p.setdefault("ptr", rng.random() < 0.3)
|
|
1962
|
+
|
|
1963
|
+
def tname(self, d):
|
|
1964
|
+
return f"{self.name}_t{d}"
|
|
1965
|
+
|
|
1966
|
+
def path(self, e, d):
|
|
1967
|
+
return f"x({e})" + "%c" * (d - 1)
|
|
1968
|
+
|
|
1969
|
+
def modules(self):
|
|
1970
|
+
D = self.p["depth"]
|
|
1971
|
+
spec = []
|
|
1972
|
+
for d in range(D, 0, -1):
|
|
1973
|
+
spec.append(f"type :: {self.tname(d)}")
|
|
1974
|
+
spec.append(" integer(8) :: s")
|
|
1975
|
+
spec.append(" integer(8), allocatable :: v(:)")
|
|
1976
|
+
if d == D and self.p["ptr"]:
|
|
1977
|
+
spec.append(" integer(8), pointer :: pv(:) => null()")
|
|
1978
|
+
if d < D:
|
|
1979
|
+
spec.append(f" type({self.tname(d + 1)}) :: c")
|
|
1980
|
+
spec.append(f"end type {self.tname(d)}")
|
|
1981
|
+
if self.p["ptr"]:
|
|
1982
|
+
spec.append(f"integer(8), target :: {self.name}_tgt"
|
|
1983
|
+
f"({self.p['m']}, {self.p['na']})")
|
|
1984
|
+
return [Module(f"{self.name}_m", spec)]
|
|
1985
|
+
|
|
1986
|
+
def uses(self):
|
|
1987
|
+
return [f"{self.name}_m"]
|
|
1988
|
+
|
|
1989
|
+
def decls(self):
|
|
1990
|
+
return [f"type({self.tname(1)}) :: x({self.p['na']})",
|
|
1991
|
+
f"integer(8) :: out({self.p['m']})", "integer :: i, e"]
|
|
1992
|
+
|
|
1993
|
+
def items(self):
|
|
1994
|
+
D, na = self.p["depth"], self.p["na"]
|
|
1995
|
+
its = []
|
|
1996
|
+
for e in range(1, na + 1):
|
|
1997
|
+
for d in range(1, D + 1):
|
|
1998
|
+
its.append(self.path(e, d) + "%v")
|
|
1999
|
+
if self.p["ptr"]:
|
|
2000
|
+
its.append(self.path(e, D) + "%pv")
|
|
2001
|
+
return its
|
|
2002
|
+
|
|
2003
|
+
def body(self):
|
|
2004
|
+
D, na, m = self.p["depth"], self.p["na"], self.p["m"]
|
|
2005
|
+
ind = " "
|
|
2006
|
+
lines = []
|
|
2007
|
+
for e in range(1, na + 1):
|
|
2008
|
+
for d in range(1, D + 1):
|
|
2009
|
+
pth = self.path(e, d)
|
|
2010
|
+
lines += [f"{ind}allocate({pth}%v({m}))",
|
|
2011
|
+
f"{ind}{pth}%s = {d * 10 + e}",
|
|
2012
|
+
f"{ind}do i = 1, {m}",
|
|
2013
|
+
f"{ind} {pth}%v(i) = mod(i * {d} + {e}, 97)",
|
|
2014
|
+
f"{ind}end do"]
|
|
2015
|
+
if self.p["ptr"]:
|
|
2016
|
+
pth = self.path(e, D)
|
|
2017
|
+
lines += [f"{ind}do i = 1, {m}",
|
|
2018
|
+
f"{ind} {self.name}_tgt(i, {e}) = i + {e}",
|
|
2019
|
+
f"{ind}end do",
|
|
2020
|
+
f"{ind}{pth}%pv => {self.name}_tgt(:, {e})"]
|
|
2021
|
+
lines.append(f"{ind}out = 0")
|
|
2022
|
+
its = self.items()
|
|
2023
|
+
o = self.o
|
|
2024
|
+
terms = []
|
|
2025
|
+
for e in range(1, na + 1):
|
|
2026
|
+
for d in range(1, D + 1):
|
|
2027
|
+
terms.append(f"{self.path(e, d)}%v(i)")
|
|
2028
|
+
terms.append(f"{self.path(e, d)}%s")
|
|
2029
|
+
if self.p["ptr"]:
|
|
2030
|
+
terms.append(f"{self.path(e, D)}%pv(i)")
|
|
2031
|
+
if self.p["mode"] == "enter":
|
|
2032
|
+
if o.model == "omp":
|
|
2033
|
+
lines.append(f"{ind}{o.sent} target enter data map(to: x)")
|
|
2034
|
+
lines += pack("target enter data", list_atoms("map", its,
|
|
2035
|
+
"to"),
|
|
2036
|
+
ind, o.sent, o.width)
|
|
2037
|
+
else:
|
|
2038
|
+
lines.append(f"{ind}{o.sent} enter data copyin(x)")
|
|
2039
|
+
lines += pack("enter data", list_atoms("copyin", its), ind,
|
|
2040
|
+
o.sent, o.width)
|
|
2041
|
+
chain = ("target teams distribute parallel do",) if \
|
|
2042
|
+
o.model == "omp" else ("parallel loop",)
|
|
2043
|
+
op, cl, ii = region(o, chain, ind, data=[("out", "tofrom")],
|
|
2044
|
+
extra=["present(x)"] if o.model == "acc"
|
|
2045
|
+
else [])
|
|
2046
|
+
else:
|
|
2047
|
+
chain = ("target teams distribute parallel do",) if \
|
|
2048
|
+
o.model == "omp" else ("parallel loop",)
|
|
2049
|
+
op, cl, ii = region(o, chain, ind,
|
|
2050
|
+
data=[("x", "to")] + [(t, "to") for t in its]
|
|
2051
|
+
+ [("out", "tofrom")])
|
|
2052
|
+
lines += op + [f"{ii}do i = 1, {m}"]
|
|
2053
|
+
lines += sum_lines(ii + " ", "out(i)", terms, o.width)
|
|
2054
|
+
lines += [f"{ii}end do"] + cl
|
|
2055
|
+
if self.p["mode"] == "enter":
|
|
2056
|
+
if o.model == "omp":
|
|
2057
|
+
lines += pack("target exit data",
|
|
2058
|
+
list_atoms("map", list(reversed(its)),
|
|
2059
|
+
"delete"), ind, o.sent, o.width)
|
|
2060
|
+
lines.append(f"{ind}{o.sent} target exit data "
|
|
2061
|
+
"map(delete: x)")
|
|
2062
|
+
else:
|
|
2063
|
+
lines += pack("exit data", list_atoms(
|
|
2064
|
+
"delete", list(reversed(its))), ind, o.sent, o.width)
|
|
2065
|
+
lines.append(f"{ind}{o.sent} exit data delete(x)")
|
|
2066
|
+
lines.append(f"{ind}call st_cksum(out, {m}, cs)")
|
|
2067
|
+
return lines
|
|
2068
|
+
|
|
2069
|
+
def value(self):
|
|
2070
|
+
D, na, m = self.p["depth"], self.p["na"], self.p["m"]
|
|
2071
|
+
vals = []
|
|
2072
|
+
for i in range(1, m + 1):
|
|
2073
|
+
t = 0
|
|
2074
|
+
for e in range(1, na + 1):
|
|
2075
|
+
for d in range(1, D + 1):
|
|
2076
|
+
t += (i * d + e) % 97 + d * 10 + e
|
|
2077
|
+
if self.p["ptr"]:
|
|
2078
|
+
t += i + e
|
|
2079
|
+
vals.append(t)
|
|
2080
|
+
return cksum(vals)
|
|
2081
|
+
|
|
2082
|
+
def smaller(self):
|
|
2083
|
+
out = []
|
|
2084
|
+
if self.p["depth"] > 1:
|
|
2085
|
+
out.append(self.clone(depth=self.p["depth"] - 1))
|
|
2086
|
+
out.append(self.clone(depth=1))
|
|
2087
|
+
if self.p["na"] > 1:
|
|
2088
|
+
out.append(self.clone(na=1))
|
|
2089
|
+
if self.p["ptr"]:
|
|
2090
|
+
out.append(self.clone(ptr=False))
|
|
2091
|
+
if self.p["mode"] == "region":
|
|
2092
|
+
out.append(self.clone(mode="enter"))
|
|
2093
|
+
return out
|
|
2094
|
+
|
|
2095
|
+
def features(self):
|
|
2096
|
+
f = super().features() | {f"dt:depth{self.p['depth']}",
|
|
2097
|
+
f"dt:mode:{self.p['mode']}",
|
|
2098
|
+
"base:derived", "base:allocatable"}
|
|
2099
|
+
if self.p["na"] > 1:
|
|
2100
|
+
f.add("dt:array_of_dt")
|
|
2101
|
+
if self.p["ptr"]:
|
|
2102
|
+
f.add("base:pointer")
|
|
2103
|
+
return f
|
|
2104
|
+
|
|
2105
|
+
|
|
2106
|
+
OO_VARIANTS = ("tbp", "nopass", "generic", "extends", "abstract", "class",
|
|
2107
|
+
"polymap", "pdt")
|
|
2108
|
+
OO_LEGAL = ("tbp", "nopass", "generic", "extends", "abstract", "class")
|
|
2109
|
+
|
|
2110
|
+
|
|
2111
|
+
class OOKernel(Kernel):
|
|
2112
|
+
"""Object-oriented code used in a target / compute region: type-bound
|
|
2113
|
+
procedures (passed-object, NOPASS), generic and operator bindings, an
|
|
2114
|
+
EXTENDS chain `depth` deep with overriding bindings, an abstract type
|
|
2115
|
+
with a deferred binding, a CLASS dummy with SELECT TYPE in a device
|
|
2116
|
+
routine; every procedure the region reaches is a device routine
|
|
2117
|
+
(OpenMP 5.0/5.2 §1.2.6: type-bound procedures accessed in a target
|
|
2118
|
+
region must appear in a declare target directive). 'polymap' maps a
|
|
2119
|
+
polymorphic allocatable: unspecified (OpenMP 6.0 §7.9.6 p.287; 5.0 and
|
|
2120
|
+
5.2 do not define it): portability data, never a compiler bug."""
|
|
2121
|
+
kind = "oo"
|
|
2122
|
+
|
|
2123
|
+
def draw(self, rng):
|
|
2124
|
+
self.p.setdefault("variant", rng.choice(OO_VARIANTS))
|
|
2125
|
+
self.p.setdefault("depth", 3)
|
|
2126
|
+
self.p.setdefault("n", 128)
|
|
2127
|
+
if self.p["variant"] == "polymap":
|
|
2128
|
+
self.legality = "unspecified"
|
|
2129
|
+
self.cite = CITES["poly"]
|
|
2130
|
+
|
|
2131
|
+
def __init__(self, name, o, rng, **p):
|
|
2132
|
+
super().__init__(name, o, rng, **p)
|
|
2133
|
+
if self.p.get("variant") == "polymap":
|
|
2134
|
+
self.legality = "unspecified"
|
|
2135
|
+
self.cite = CITES["poly"]
|
|
2136
|
+
|
|
2137
|
+
def t(self, d=0):
|
|
2138
|
+
return f"{self.name}_t{d}"
|
|
2139
|
+
|
|
2140
|
+
def modules(self):
|
|
2141
|
+
v, D = self.p["variant"], self.p["depth"]
|
|
2142
|
+
dt = _dt_line(self.o)
|
|
2143
|
+
spec, cont = [], []
|
|
2144
|
+
if v in ("tbp", "class", "polymap"):
|
|
2145
|
+
spec = [f"type :: {self.t()}", " integer(8) :: k = 3",
|
|
2146
|
+
"contains",
|
|
2147
|
+
f" procedure :: get => {self.name}_get",
|
|
2148
|
+
f"end type {self.t()}"]
|
|
2149
|
+
cont = [f" function {self.name}_get(self, i) result(r)", dt,
|
|
2150
|
+
f" class({self.t()}), intent(in) :: self",
|
|
2151
|
+
" integer(8), intent(in) :: i", " integer(8) :: r",
|
|
2152
|
+
" r = self%k * i + 1", f" end function {self.name}_get"]
|
|
2153
|
+
if v in ("class", "polymap"):
|
|
2154
|
+
spec += [f"type, extends({self.t()}) :: {self.t(1)}",
|
|
2155
|
+
" integer(8) :: extra = 5",
|
|
2156
|
+
"contains", f" procedure :: get => {self.name}_get1",
|
|
2157
|
+
f"end type {self.t(1)}"]
|
|
2158
|
+
cont += [f" function {self.name}_get1(self, i) result(r)",
|
|
2159
|
+
dt, f" class({self.t(1)}), intent(in) :: self",
|
|
2160
|
+
" integer(8), intent(in) :: i",
|
|
2161
|
+
" integer(8) :: r",
|
|
2162
|
+
" r = self%k * i + self%extra",
|
|
2163
|
+
f" end function {self.name}_get1",
|
|
2164
|
+
f" function {self.name}_sel(o, i) result(r)", dt,
|
|
2165
|
+
f" class({self.t()}), intent(in) :: o",
|
|
2166
|
+
" integer(8), intent(in) :: i",
|
|
2167
|
+
" integer(8) :: r",
|
|
2168
|
+
" select type (o)",
|
|
2169
|
+
f" type is ({self.t(1)})",
|
|
2170
|
+
" r = o%extra * 100 + o%get(i)",
|
|
2171
|
+
" class default",
|
|
2172
|
+
" r = o%get(i)",
|
|
2173
|
+
" end select",
|
|
2174
|
+
f" end function {self.name}_sel"]
|
|
2175
|
+
elif v == "nopass":
|
|
2176
|
+
spec = [f"type :: {self.t()}", " integer(8) :: k = 3",
|
|
2177
|
+
"contains",
|
|
2178
|
+
f" procedure, nopass :: f => {self.name}_f",
|
|
2179
|
+
f"end type {self.t()}"]
|
|
2180
|
+
cont = [f" function {self.name}_f(i) result(r)", dt,
|
|
2181
|
+
" integer(8), intent(in) :: i", " integer(8) :: r",
|
|
2182
|
+
" r = i * 7 + 2", f" end function {self.name}_f"]
|
|
2183
|
+
elif v == "generic":
|
|
2184
|
+
spec = [f"type :: {self.t()}", " integer(8) :: k = 3",
|
|
2185
|
+
"contains",
|
|
2186
|
+
f" procedure :: addi => {self.name}_addi",
|
|
2187
|
+
" generic :: add => addi",
|
|
2188
|
+
f" procedure :: plus => {self.name}_plus",
|
|
2189
|
+
" generic :: operator(+) => plus",
|
|
2190
|
+
f"end type {self.t()}"]
|
|
2191
|
+
cont = [f" function {self.name}_addi(self, i) result(r)", dt,
|
|
2192
|
+
f" class({self.t()}), intent(in) :: self",
|
|
2193
|
+
" integer(8), intent(in) :: i", " integer(8) :: r",
|
|
2194
|
+
" r = self%k + i", f" end function {self.name}_addi",
|
|
2195
|
+
f" function {self.name}_plus(a, b) result(r)", dt,
|
|
2196
|
+
f" class({self.t()}), intent(in) :: a",
|
|
2197
|
+
f" type({self.t()}), intent(in) :: b",
|
|
2198
|
+
f" type({self.t()}) :: r",
|
|
2199
|
+
" r%k = a%k + b%k", f" end function {self.name}_plus"]
|
|
2200
|
+
elif v == "extends":
|
|
2201
|
+
for d in range(D + 1):
|
|
2202
|
+
head = f"type :: {self.t(0)}" if d == 0 else \
|
|
2203
|
+
f"type, extends({self.t(d - 1)}) :: {self.t(d)}"
|
|
2204
|
+
spec += [head, f" integer(8) :: c{d} = {d + 2}", "contains",
|
|
2205
|
+
f" procedure :: get => {self.name}_g{d}",
|
|
2206
|
+
f"end type {self.t(d)}"]
|
|
2207
|
+
cont += [f" function {self.name}_g{d}(self, i) result(r)",
|
|
2208
|
+
dt, f" class({self.t(d)}), intent(in) :: self",
|
|
2209
|
+
" integer(8), intent(in) :: i",
|
|
2210
|
+
" integer(8) :: r",
|
|
2211
|
+
f" r = self%c{d} * i + {d}",
|
|
2212
|
+
f" end function {self.name}_g{d}"]
|
|
2213
|
+
elif v == "pdt":
|
|
2214
|
+
# a parameterized derived type (kind and length parameters;
|
|
2215
|
+
# OpenMP 5.2 §5.8.3: a corresponding list item has the type
|
|
2216
|
+
# parameters of the original)
|
|
2217
|
+
spec = [f"type :: {self.t()}(kk, nn)",
|
|
2218
|
+
" integer, kind :: kk = 8", " integer, len :: nn",
|
|
2219
|
+
" integer(kk) :: v(nn)", " integer(kk) :: s",
|
|
2220
|
+
f"end type {self.t()}"]
|
|
2221
|
+
cont = []
|
|
2222
|
+
elif v == "abstract":
|
|
2223
|
+
spec = [f"type, abstract :: {self.t(0)}", " integer(8) :: k = 4",
|
|
2224
|
+
"contains",
|
|
2225
|
+
f" procedure({self.name}_iface), deferred :: get",
|
|
2226
|
+
f"end type {self.t(0)}",
|
|
2227
|
+
"abstract interface",
|
|
2228
|
+
f" function {self.name}_iface(self, i) result(r)",
|
|
2229
|
+
f" import :: {self.t(0)}",
|
|
2230
|
+
f" class({self.t(0)}), intent(in) :: self",
|
|
2231
|
+
" integer(8), intent(in) :: i", " integer(8) :: r",
|
|
2232
|
+
f" end function {self.name}_iface", "end interface",
|
|
2233
|
+
f"type, extends({self.t(0)}) :: {self.t(1)}", "contains",
|
|
2234
|
+
f" procedure :: get => {self.name}_g1",
|
|
2235
|
+
f"end type {self.t(1)}"]
|
|
2236
|
+
cont = [f" function {self.name}_g1(self, i) result(r)", dt,
|
|
2237
|
+
f" class({self.t(1)}), intent(in) :: self",
|
|
2238
|
+
" integer(8), intent(in) :: i", " integer(8) :: r",
|
|
2239
|
+
" r = self%k * i * 2", f" end function {self.name}_g1"]
|
|
2240
|
+
return [Module(f"{self.name}_m", spec, cont)]
|
|
2241
|
+
|
|
2242
|
+
def uses(self):
|
|
2243
|
+
return [f"{self.name}_m"]
|
|
2244
|
+
|
|
2245
|
+
def decls(self):
|
|
2246
|
+
v = self.p["variant"]
|
|
2247
|
+
d = [f"integer(8) :: out({self.p['n']})", "integer :: i"]
|
|
2248
|
+
if v in ("tbp", "nopass", "generic"):
|
|
2249
|
+
d.append(f"type({self.t()}) :: obj")
|
|
2250
|
+
if v == "generic":
|
|
2251
|
+
d.append(f"type({self.t()}) :: o2")
|
|
2252
|
+
if v == "extends":
|
|
2253
|
+
d.append(f"type({self.t(self.p['depth'])}) :: obj")
|
|
2254
|
+
if v == "abstract":
|
|
2255
|
+
d.append(f"type({self.t(1)}) :: obj")
|
|
2256
|
+
if v == "class":
|
|
2257
|
+
d.append(f"type({self.t(1)}) :: obj")
|
|
2258
|
+
if v == "polymap":
|
|
2259
|
+
d.append(f"class({self.t()}), allocatable :: obj")
|
|
2260
|
+
if v == "pdt":
|
|
2261
|
+
d.append(f"type({self.t()}(8, 7)) :: obj")
|
|
2262
|
+
return d
|
|
2263
|
+
|
|
2264
|
+
def expr(self):
|
|
2265
|
+
v = self.p["variant"]
|
|
2266
|
+
return {"tbp": "obj%get(int(i, 8))",
|
|
2267
|
+
"nopass": "obj%f(int(i, 8))",
|
|
2268
|
+
"generic": "obj%add(int(i, 8)) + o2%k",
|
|
2269
|
+
"extends": "obj%get(int(i, 8)) + obj%c0",
|
|
2270
|
+
"abstract": "obj%get(int(i, 8))",
|
|
2271
|
+
"class": f"{self.name}_sel(obj, int(i, 8))",
|
|
2272
|
+
"polymap": "obj%get(int(i, 8))",
|
|
2273
|
+
"pdt": "obj%v(mod(i, obj%nn) + 1) + obj%s + obj%nn"}[v]
|
|
2274
|
+
|
|
2275
|
+
def body(self):
|
|
2276
|
+
v = self.p["variant"]
|
|
2277
|
+
n = self.p["n"]
|
|
2278
|
+
ind = " "
|
|
2279
|
+
lines = [f"{ind}out = 0"]
|
|
2280
|
+
if v == "generic":
|
|
2281
|
+
lines.append(f"{ind}o2 = obj + obj")
|
|
2282
|
+
if v == "polymap":
|
|
2283
|
+
lines.append(f"{ind}allocate({self.t(1)} :: obj)")
|
|
2284
|
+
if v == "pdt":
|
|
2285
|
+
lines += [f"{ind}do i = 1, 7", f"{ind} obj%v(i) = i * 11",
|
|
2286
|
+
f"{ind}end do", f"{ind}obj%s = 5"]
|
|
2287
|
+
chain = ("target teams distribute parallel do",) if \
|
|
2288
|
+
self.o.model == "omp" else ("parallel loop",)
|
|
2289
|
+
data = [("out", "tofrom"), ("obj", "to")]
|
|
2290
|
+
if v == "generic":
|
|
2291
|
+
data.append(("o2", "to"))
|
|
2292
|
+
op, cl, ii = region(self.o, chain, ind, data=data)
|
|
2293
|
+
lines += op + [f"{ii}do i = 1, {n}",
|
|
2294
|
+
f"{ii} out(i) = {self.expr()}", f"{ii}end do"] + cl
|
|
2295
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
2296
|
+
return lines
|
|
2297
|
+
|
|
2298
|
+
def value(self):
|
|
2299
|
+
v, n, D = self.p["variant"], self.p["n"], self.p["depth"]
|
|
2300
|
+
f = {"tbp": lambda i: 3 * i + 1,
|
|
2301
|
+
"nopass": lambda i: i * 7 + 2,
|
|
2302
|
+
"generic": lambda i: 3 + i + 6,
|
|
2303
|
+
"extends": lambda i: (D + 2) * i + D + 2,
|
|
2304
|
+
"abstract": lambda i: 4 * i * 2,
|
|
2305
|
+
"class": lambda i: 5 * 100 + 3 * i + 5,
|
|
2306
|
+
"polymap": lambda i: 3 * i + 5,
|
|
2307
|
+
"pdt": lambda i: (i % 7 + 1) * 11 + 5 + 7}[v]
|
|
2308
|
+
return cksum(f(i) for i in range(1, n + 1))
|
|
2309
|
+
|
|
2310
|
+
def smaller(self):
|
|
2311
|
+
out = []
|
|
2312
|
+
if self.p["variant"] == "extends" and self.p["depth"] > 1:
|
|
2313
|
+
out.append(self.clone(depth=1))
|
|
2314
|
+
if self.p["n"] > 8:
|
|
2315
|
+
out.append(self.clone(n=8))
|
|
2316
|
+
return out
|
|
2317
|
+
|
|
2318
|
+
def features(self):
|
|
2319
|
+
return super().features() | {f"oo:{self.p['variant']}",
|
|
2320
|
+
"base:derived"}
|
|
2321
|
+
|
|
2322
|
+
|
|
2323
|
+
# --- translation units ---------------------------------------------------------------------------
|
|
2324
|
+
|
|
2325
|
+
class ChainTUKernel(Kernel):
|
|
2326
|
+
"""A device call chain across modules: module <k>_c1 uses <k>_c2 ...
|
|
2327
|
+
uses <k>_cD, each with function g_j(x) = g_{j+1}(mod(x*5, 1013) + j)
|
|
2328
|
+
+ j; every module also uses <k>_glob, whose declare target variable gv
|
|
2329
|
+
the deepest function adds (a module DAG with a shared root). Variants:
|
|
2330
|
+
'plain'; 'submodule' (the deepest function's interface in the module,
|
|
2331
|
+
its body in a submodule); 'bindc' (the deepest function in C, bound
|
|
2332
|
+
with bind(C), OpenMP only); 'implicit' (no declare target on g_2..g_D:
|
|
2333
|
+
legal when every g_j is in the compilation unit of the region,
|
|
2334
|
+
otherwise an illegal probe, OpenMP 5.2 §13.8 p.284 and §5.8.4 p.158).
|
|
2335
|
+
The program's layout decides the files (one per module, or
|
|
2336
|
+
partitions)."""
|
|
2337
|
+
kind = "tu"
|
|
2338
|
+
|
|
2339
|
+
def draw(self, rng):
|
|
2340
|
+
self.p.setdefault("depth", 5)
|
|
2341
|
+
self.p.setdefault("n", 256)
|
|
2342
|
+
self.p.setdefault("variant", "plain")
|
|
2343
|
+
self.p.setdefault("gv", rng.randrange(1, 100))
|
|
2344
|
+
|
|
2345
|
+
def m(self, j):
|
|
2346
|
+
return f"{self.name}_c{j}"
|
|
2347
|
+
|
|
2348
|
+
def g(self, j):
|
|
2349
|
+
return f"{self.name}_g{j}"
|
|
2350
|
+
|
|
2351
|
+
def modules(self):
|
|
2352
|
+
D, var = self.p["depth"], self.p["variant"]
|
|
2353
|
+
o = self.o
|
|
2354
|
+
mods = []
|
|
2355
|
+
glob_spec = ["integer(8) :: gv = 0"]
|
|
2356
|
+
glob_spec.append(f"{o.sent} declare target(gv)" if o.model == "omp"
|
|
2357
|
+
else f"{o.sent} declare create(gv)")
|
|
2358
|
+
mods.append(Module(f"{self.name}_glob", glob_spec))
|
|
2359
|
+
for j in range(D, 0, -1):
|
|
2360
|
+
uses = [f"{self.name}_glob"] + ([self.m(j + 1)] if j < D else [])
|
|
2361
|
+
need_dt = not (var == "implicit" and j > 1)
|
|
2362
|
+
dl = [_dt_line(o)] if need_dt else []
|
|
2363
|
+
if j == D and var == "submodule":
|
|
2364
|
+
spec = ["interface",
|
|
2365
|
+
f" module function {self.g(j)}(x) result(r)",
|
|
2366
|
+
f" {o.sent} declare target" if o.model == "omp"
|
|
2367
|
+
else f" {o.sent} routine seq",
|
|
2368
|
+
" integer(8), intent(in) :: x",
|
|
2369
|
+
" integer(8) :: r",
|
|
2370
|
+
f" end function {self.g(j)}", "end interface"]
|
|
2371
|
+
mods.append(Module(self.m(j), spec, [], uses))
|
|
2372
|
+
continue
|
|
2373
|
+
if j == D and var == "bindc":
|
|
2374
|
+
spec = ["interface",
|
|
2375
|
+
f" function {self.g(j)}(x) result(r) "
|
|
2376
|
+
f"bind(C, name=\"{self.g(j)}_c\")",
|
|
2377
|
+
" import :: c_int64_t",
|
|
2378
|
+
f" {o.sent} declare target",
|
|
2379
|
+
" integer(c_int64_t), value :: x",
|
|
2380
|
+
" integer(c_int64_t) :: r",
|
|
2381
|
+
f" end function {self.g(j)}", "end interface"]
|
|
2382
|
+
mods.append(Module(self.m(j), spec, [],
|
|
2383
|
+
uses + ["iso_c_binding"]))
|
|
2384
|
+
continue
|
|
2385
|
+
cont = [f" function {self.g(j)}(x) result(r)"] + dl + [
|
|
2386
|
+
" integer(8), intent(in) :: x", " integer(8) :: r"]
|
|
2387
|
+
if j < D:
|
|
2388
|
+
cont.append(f" r = {self.g(j + 1)}(mod(x * 5, 1013_8) + "
|
|
2389
|
+
f"{j}) + {j}")
|
|
2390
|
+
else:
|
|
2391
|
+
cont.append(" r = x + gv")
|
|
2392
|
+
cont.append(f" end function {self.g(j)}")
|
|
2393
|
+
mods.append(Module(self.m(j), [], cont, uses))
|
|
2394
|
+
return mods
|
|
2395
|
+
|
|
2396
|
+
def extra_files(self) -> list[tuple[str, str]]:
|
|
2397
|
+
"""Files that are not modules of the program text: the submodule
|
|
2398
|
+
and the C function, each its own translation unit."""
|
|
2399
|
+
D, var = self.p["depth"], self.p["variant"]
|
|
2400
|
+
o = self.o
|
|
2401
|
+
if var == "submodule":
|
|
2402
|
+
text = [f"submodule ({self.m(D)}) {self.m(D)}_s",
|
|
2403
|
+
" implicit none", "contains",
|
|
2404
|
+
f" module function {self.g(D)}(x) result(r)",
|
|
2405
|
+
" use " + f"{self.name}_glob, only: gv",
|
|
2406
|
+
f" {o.sent} declare target" if o.model == "omp"
|
|
2407
|
+
else f" {o.sent} routine seq",
|
|
2408
|
+
" integer(8), intent(in) :: x",
|
|
2409
|
+
" integer(8) :: r",
|
|
2410
|
+
" r = x + gv", f" end function {self.g(D)}",
|
|
2411
|
+
f"end submodule {self.m(D)}_s"]
|
|
2412
|
+
return [(f"{self.m(D)}_s.f90", "\n".join(text) + "\n")]
|
|
2413
|
+
if var == "bindc":
|
|
2414
|
+
text = ["#include <stdint.h>",
|
|
2415
|
+
"#pragma omp declare target",
|
|
2416
|
+
f"int64_t {self.g(D)}_c(int64_t x) {{ return x + "
|
|
2417
|
+
f"{self.p['gv']}; }}",
|
|
2418
|
+
"#pragma omp end declare target"]
|
|
2419
|
+
return [(f"{self.g(D)}_c.c", "\n".join(text) + "\n")]
|
|
2420
|
+
return []
|
|
2421
|
+
|
|
2422
|
+
def uses(self):
|
|
2423
|
+
return [self.m(1), f"{self.name}_glob"]
|
|
2424
|
+
|
|
2425
|
+
def decls(self):
|
|
2426
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i"]
|
|
2427
|
+
|
|
2428
|
+
def body(self):
|
|
2429
|
+
n = self.p["n"]
|
|
2430
|
+
o = self.o
|
|
2431
|
+
ind = " "
|
|
2432
|
+
lines = [f"{ind}gv = {self.p['gv']}"]
|
|
2433
|
+
lines.append(f"{ind}{o.sent} target update to(gv)" if o.model ==
|
|
2434
|
+
"omp" else f"{ind}{o.sent} update device(gv)")
|
|
2435
|
+
chain = ("target teams distribute parallel do",) if \
|
|
2436
|
+
o.model == "omp" else ("parallel loop gang vector",)
|
|
2437
|
+
op, cl, ii = region(o, chain, ind, data=[("out", "tofrom")])
|
|
2438
|
+
lines += [f"{ind}out = 0"] + op + [
|
|
2439
|
+
f"{ii}do i = 1, {n}", f"{ii} out(i) = {self.g(1)}(int(i, 8))",
|
|
2440
|
+
f"{ii}end do"] + cl
|
|
2441
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
2442
|
+
return lines
|
|
2443
|
+
|
|
2444
|
+
def value(self):
|
|
2445
|
+
D, n, gv = self.p["depth"], self.p["n"], self.p["gv"]
|
|
2446
|
+
vals = []
|
|
2447
|
+
for i in range(1, n + 1):
|
|
2448
|
+
x, add = i, 0
|
|
2449
|
+
for j in range(1, D):
|
|
2450
|
+
x = (x * 5) % 1013 + j
|
|
2451
|
+
add += j
|
|
2452
|
+
vals.append(x + gv + add)
|
|
2453
|
+
return cksum(vals)
|
|
2454
|
+
|
|
2455
|
+
def smaller(self):
|
|
2456
|
+
out = [self.clone(depth=m) for m in _halve(self.p["depth"], 2)]
|
|
2457
|
+
if self.p["variant"] != "plain":
|
|
2458
|
+
out.append(self.clone(variant="plain"))
|
|
2459
|
+
return out
|
|
2460
|
+
|
|
2461
|
+
def features(self):
|
|
2462
|
+
return super().features() | {f"tu:depth{self.p['depth']}",
|
|
2463
|
+
f"tu:{self.p['variant']}"}
|
|
2464
|
+
|
|
2465
|
+
|
|
2466
|
+
# --- default scalar residency ------------------------------------------------------------------
|
|
2467
|
+
|
|
2468
|
+
# route -> (defined: device read of the host value, defined: host value
|
|
2469
|
+
# after the region, what the host sees after: "same" | "write")
|
|
2470
|
+
OMP_ROUTES = {
|
|
2471
|
+
"implicit": (True, True, "same"),
|
|
2472
|
+
"firstprivate": (True, True, "same"),
|
|
2473
|
+
"private": (False, True, "same"),
|
|
2474
|
+
"to": (True, False, None),
|
|
2475
|
+
"from": (False, True, "write"),
|
|
2476
|
+
"tofrom": (True, True, "write"),
|
|
2477
|
+
"dm_tofrom": (True, True, "write"),
|
|
2478
|
+
"dm_firstprivate": (True, True, "same"),
|
|
2479
|
+
"dm_to": (True, False, None),
|
|
2480
|
+
"target_attr": (True, True, "write"),
|
|
2481
|
+
"present_implicit": (True, True, "same"),
|
|
2482
|
+
"present_update": (True, True, "write"),
|
|
2483
|
+
"declare": (True, True, "write"),
|
|
2484
|
+
"component": (True, True, "write"),
|
|
2485
|
+
"byref": (True, True, "same"),
|
|
2486
|
+
"value": (True, True, "same"),
|
|
2487
|
+
"reduction": (True, True, "red"),
|
|
2488
|
+
}
|
|
2489
|
+
ACC_ROUTES = {
|
|
2490
|
+
"implicit_parallel": (True, True, "same"),
|
|
2491
|
+
"implicit_serial": (True, True, "same"),
|
|
2492
|
+
"implicit_kernels": (True, True, "write"),
|
|
2493
|
+
"copy": (True, True, "write"),
|
|
2494
|
+
"copyin": (True, False, None),
|
|
2495
|
+
"copyout": (False, True, "write"),
|
|
2496
|
+
"firstprivate": (True, True, "same"),
|
|
2497
|
+
"private": (False, True, "same"),
|
|
2498
|
+
"data_copy": (True, True, "write"),
|
|
2499
|
+
"enter_implicit": (True, True, "same"),
|
|
2500
|
+
"declare": (True, True, "write"),
|
|
2501
|
+
"component": (True, True, "write"),
|
|
2502
|
+
"byref": (True, True, "same"),
|
|
2503
|
+
"reduction": (True, True, "red"),
|
|
2504
|
+
}
|
|
2505
|
+
ROUTE_CITES = (
|
|
2506
|
+
"OpenMP 5.2 §5.8.1 p.147-148 (implicit data-mapping: a non-scalar or a "
|
|
2507
|
+
"TARGET/ALLOCATABLE/POINTER scalar is tofrom, another scalar "
|
|
2508
|
+
"firstprivate; the same rules in 5.0 §2.19.7 p.314 and 6.0 §7.9.3 "
|
|
2509
|
+
"p.276), §1.4.2 p.27 (a write to a variable whose corresponding "
|
|
2510
|
+
"variable does not share storage makes the other undefined); OpenACC "
|
|
2511
|
+
"3.4 §2.6.2 p.41 (a scalar is copy in kernels, firstprivate otherwise; "
|
|
2512
|
+
"a visible data clause of an enclosing data construct applies)")
|
|
2513
|
+
|
|
2514
|
+
|
|
2515
|
+
class ScalarsKernel(Kernel):
|
|
2516
|
+
"""Default scalar residency against every explicit route: for each
|
|
2517
|
+
route, `nscal` scalars s_j (host value h_j) and an array a mixed in the
|
|
2518
|
+
same region; one thread on the device (target / serial) reads each s_j
|
|
2519
|
+
into rd(j) and writes s_j = 2*s_j + 1. The value combines only the
|
|
2520
|
+
observations the specification defines (a device read of the host
|
|
2521
|
+
value; the host value afterwards: unchanged for private copies, the
|
|
2522
|
+
device write for tofrom); the others print an ``OBS`` line
|
|
2523
|
+
(portability data)."""
|
|
2524
|
+
kind = "scalars"
|
|
2525
|
+
elision_valid = False
|
|
2526
|
+
|
|
2527
|
+
def draw(self, rng):
|
|
2528
|
+
self.p.setdefault("nscal", 4)
|
|
2529
|
+
routes = OMP_ROUTES if self.o.model == "omp" else ACC_ROUTES
|
|
2530
|
+
self.p.setdefault("routes", list(routes))
|
|
2531
|
+
|
|
2532
|
+
def table(self):
|
|
2533
|
+
return OMP_ROUTES if self.o.model == "omp" else ACC_ROUTES
|
|
2534
|
+
|
|
2535
|
+
def mod(self):
|
|
2536
|
+
return f"{self.name}_m"
|
|
2537
|
+
|
|
2538
|
+
def svars(self, r):
|
|
2539
|
+
return [f"s{r}_{j}" for j in range(1, self.p["nscal"] + 1)]
|
|
2540
|
+
|
|
2541
|
+
def modules(self):
|
|
2542
|
+
spec, cont = [], []
|
|
2543
|
+
o = self.o
|
|
2544
|
+
if "declare" in self.p["routes"]:
|
|
2545
|
+
dv = [f"g_{j}" for j in range(1, self.p["nscal"] + 1)]
|
|
2546
|
+
spec += decl_lines("integer(8)", dv, o.width)
|
|
2547
|
+
if o.model == "omp":
|
|
2548
|
+
spec += pack("declare target(", [
|
|
2549
|
+
x + ("," if k < len(dv) - 1 else ")")
|
|
2550
|
+
for k, x in enumerate(dv)], "", o.sent, o.width)
|
|
2551
|
+
else:
|
|
2552
|
+
spec += pack("declare", list_atoms("create", dv), "",
|
|
2553
|
+
o.sent, o.width)
|
|
2554
|
+
if "component" in self.p["routes"]:
|
|
2555
|
+
spec += [f"type :: {self.name}_sc",
|
|
2556
|
+
*[f" integer(8) :: c{j}" for j in
|
|
2557
|
+
range(1, self.p["nscal"] + 1)],
|
|
2558
|
+
f"end type {self.name}_sc"]
|
|
2559
|
+
cont += [f" subroutine {self.name}_upd(x)", _dt_line(o),
|
|
2560
|
+
" integer(8), intent(inout) :: x",
|
|
2561
|
+
" x = 2 * x + 1", f" end subroutine {self.name}_upd",
|
|
2562
|
+
f" function {self.name}_val(x) result(r)", _dt_line(o),
|
|
2563
|
+
" integer(8), value :: x", " integer(8) :: r",
|
|
2564
|
+
" x = 2 * x + 1", " r = x",
|
|
2565
|
+
f" end function {self.name}_val"]
|
|
2566
|
+
return [Module(self.mod(), spec, cont)]
|
|
2567
|
+
|
|
2568
|
+
def uses(self):
|
|
2569
|
+
return [self.mod()]
|
|
2570
|
+
|
|
2571
|
+
def decls(self):
|
|
2572
|
+
k = self.p["nscal"]
|
|
2573
|
+
d = [f"integer(8) :: rd({k}), a(4), hv", "integer :: j, ii"]
|
|
2574
|
+
for r, route in enumerate(self.p["routes"]):
|
|
2575
|
+
if route in ("declare", "component"):
|
|
2576
|
+
continue
|
|
2577
|
+
attr = ", target" if route == "target_attr" else ""
|
|
2578
|
+
d += decl_lines(f"integer(8){attr}", self.svars(r), self.o.width)
|
|
2579
|
+
if "component" in self.p["routes"]:
|
|
2580
|
+
d.append(f"type({self.name}_sc) :: xc")
|
|
2581
|
+
return d
|
|
2582
|
+
|
|
2583
|
+
def h(self, r, j):
|
|
2584
|
+
return 100 * (r + 1) + j
|
|
2585
|
+
|
|
2586
|
+
def names(self, r, route):
|
|
2587
|
+
k = self.p["nscal"]
|
|
2588
|
+
if route == "declare":
|
|
2589
|
+
return [f"g_{j}" for j in range(1, k + 1)]
|
|
2590
|
+
if route == "component":
|
|
2591
|
+
return [f"xc%c{j}" for j in range(1, k + 1)]
|
|
2592
|
+
return self.svars(r)
|
|
2593
|
+
|
|
2594
|
+
def route_lines(self, r, route) -> list[str]:
|
|
2595
|
+
o = self.o
|
|
2596
|
+
ind = " "
|
|
2597
|
+
S = self.names(r, route)
|
|
2598
|
+
k = len(S)
|
|
2599
|
+
lines = [f"{ind}! route {route}", f"{ind}rd = -1", f"{ind}a = 0"]
|
|
2600
|
+
lines += [f"{ind}{s} = {self.h(r, j)}" for j, s in enumerate(S, 1)]
|
|
2601
|
+
read_first = OMP_ROUTES.get(route, ACC_ROUTES.get(route))[0]
|
|
2602
|
+
dev = []
|
|
2603
|
+
if route in ("from", "copyout"):
|
|
2604
|
+
dev += [f"{s} = {self.h(r, j)} + 0" for j, s in enumerate(S, 1)]
|
|
2605
|
+
if route == "private":
|
|
2606
|
+
dev += [f"{s} = {j} * 5" for j, s in enumerate(S, 1)]
|
|
2607
|
+
if route == "byref":
|
|
2608
|
+
dev += [f"rd({j}) = {s}" for j, s in enumerate(S, 1)]
|
|
2609
|
+
dev += [f"call {self.name}_upd({s})" for s in S]
|
|
2610
|
+
dev += [f"a({min(4, j)}) = a({min(4, j)}) + {s}"
|
|
2611
|
+
for j, s in enumerate(S, 1)]
|
|
2612
|
+
elif route == "value":
|
|
2613
|
+
dev += [f"rd({j}) = {self.name}_val({s}) - {s}"
|
|
2614
|
+
for j, s in enumerate(S, 1)]
|
|
2615
|
+
dev += [f"a(1) = a(1) + {s}" for s in S]
|
|
2616
|
+
elif route == "reduction":
|
|
2617
|
+
pass
|
|
2618
|
+
else:
|
|
2619
|
+
dev += [f"rd({j}) = {s}" for j, s in enumerate(S, 1)]
|
|
2620
|
+
dev += [f"{s} = 2 * {s} + 1" for s in S]
|
|
2621
|
+
dev += ["a(1) = a(1) + 1"]
|
|
2622
|
+
pre, post = [], []
|
|
2623
|
+
atoms = []
|
|
2624
|
+
name = "target" if o.model == "omp" else "serial"
|
|
2625
|
+
data = [("rd", "tofrom"), ("a", "tofrom")]
|
|
2626
|
+
if o.model == "omp":
|
|
2627
|
+
if route in ("firstprivate", "private"):
|
|
2628
|
+
atoms = list_atoms(route, S)
|
|
2629
|
+
elif route in ("to", "from", "tofrom"):
|
|
2630
|
+
data = [(s, route) for s in S] + data
|
|
2631
|
+
elif route.startswith("dm_"):
|
|
2632
|
+
atoms = [f"defaultmap({route[3:]}: scalar)"]
|
|
2633
|
+
elif route == "present_implicit":
|
|
2634
|
+
pre += pack("target enter data", list_atoms("map", S, "to"),
|
|
2635
|
+
ind, o.sent, o.width)
|
|
2636
|
+
pre += [f"{ind}{s} = {self.h(r, j)} + 1000"
|
|
2637
|
+
for j, s in enumerate(S, 1)]
|
|
2638
|
+
post += pack("target exit data", list_atoms("map", S,
|
|
2639
|
+
"delete"),
|
|
2640
|
+
ind, o.sent, o.width)
|
|
2641
|
+
elif route == "present_update":
|
|
2642
|
+
pre += pack("target enter data", list_atoms("map", S, "to"),
|
|
2643
|
+
ind, o.sent, o.width)
|
|
2644
|
+
pre += [f"{ind}{s} = {self.h(r, j)} + 1000"
|
|
2645
|
+
for j, s in enumerate(S, 1)]
|
|
2646
|
+
pre += pack("target update", list_atoms("to", S), ind,
|
|
2647
|
+
o.sent, o.width)
|
|
2648
|
+
data = [(s, "tofrom") for s in S] + data
|
|
2649
|
+
post += pack("target update", list_atoms("from", S), ind,
|
|
2650
|
+
o.sent, o.width)
|
|
2651
|
+
post += pack("target exit data", list_atoms("map", S,
|
|
2652
|
+
"delete"),
|
|
2653
|
+
ind, o.sent, o.width)
|
|
2654
|
+
elif route == "declare":
|
|
2655
|
+
pre += pack("target update", list_atoms("to", S), ind,
|
|
2656
|
+
o.sent, o.width)
|
|
2657
|
+
post += pack("target update", list_atoms("from", S), ind,
|
|
2658
|
+
o.sent, o.width)
|
|
2659
|
+
elif route == "reduction":
|
|
2660
|
+
name = "target teams distribute parallel do"
|
|
2661
|
+
atoms = list_atoms("reduction", S, "+")
|
|
2662
|
+
else:
|
|
2663
|
+
if route == "implicit_parallel":
|
|
2664
|
+
name = "parallel"
|
|
2665
|
+
atoms = ["num_gangs(1)"]
|
|
2666
|
+
elif route == "implicit_kernels":
|
|
2667
|
+
name = "kernels"
|
|
2668
|
+
elif route in ("copy", "copyin", "copyout", "firstprivate",
|
|
2669
|
+
"private"):
|
|
2670
|
+
atoms = list_atoms(route, S)
|
|
2671
|
+
elif route == "data_copy":
|
|
2672
|
+
pre += pack("data", list_atoms("copy", S), ind, o.sent,
|
|
2673
|
+
o.width)
|
|
2674
|
+
post += [f"{ind}{o.sent} end data"]
|
|
2675
|
+
elif route == "enter_implicit":
|
|
2676
|
+
pre += pack("enter data", list_atoms("copyin", S), ind,
|
|
2677
|
+
o.sent, o.width)
|
|
2678
|
+
pre += [f"{ind}{s} = {self.h(r, j)} + 1000"
|
|
2679
|
+
for j, s in enumerate(S, 1)]
|
|
2680
|
+
post += pack("exit data", list_atoms("delete", S), ind,
|
|
2681
|
+
o.sent, o.width)
|
|
2682
|
+
elif route == "declare":
|
|
2683
|
+
pre += pack("update", list_atoms("device", S), ind, o.sent,
|
|
2684
|
+
o.width)
|
|
2685
|
+
post += pack("update", list_atoms("self", S), ind, o.sent,
|
|
2686
|
+
o.width)
|
|
2687
|
+
elif route == "reduction":
|
|
2688
|
+
name = "parallel loop"
|
|
2689
|
+
atoms = list_atoms("reduction", S, "+")
|
|
2690
|
+
lines += pre
|
|
2691
|
+
lines += pack(name, data_clauses(o, data) + atoms, ind, o.sent,
|
|
2692
|
+
o.width)
|
|
2693
|
+
if route == "reduction":
|
|
2694
|
+
lines += [f"{ind}do ii = 1, 4"]
|
|
2695
|
+
lines += [f"{ind} {s} = {s} + {j}" for j, s in enumerate(S, 1)]
|
|
2696
|
+
lines += [f"{ind}end do"]
|
|
2697
|
+
else:
|
|
2698
|
+
lines += [f"{ind} {x}" for x in dev]
|
|
2699
|
+
if not (o.model == "acc" and name == "parallel loop"):
|
|
2700
|
+
lines.append(f"{ind}{o.sent} end {name}")
|
|
2701
|
+
lines += post
|
|
2702
|
+
del read_first, k
|
|
2703
|
+
return lines
|
|
2704
|
+
|
|
2705
|
+
def expect(self, r, route):
|
|
2706
|
+
"""(rd values or None per j, host-after values or None per j)."""
|
|
2707
|
+
dr, da, after = self.table()[route]
|
|
2708
|
+
k = self.p["nscal"]
|
|
2709
|
+
hs = [self.h(r, j) + (1000 if route in ("present_implicit",
|
|
2710
|
+
"present_update",
|
|
2711
|
+
"enter_implicit") else 0)
|
|
2712
|
+
for j in range(1, k + 1)]
|
|
2713
|
+
rd = [None] * k
|
|
2714
|
+
aft = [None] * k
|
|
2715
|
+
for j in range(k):
|
|
2716
|
+
if route == "private":
|
|
2717
|
+
rd[j] = (j + 1) * 5
|
|
2718
|
+
elif route == "from" or route == "copyout":
|
|
2719
|
+
rd[j] = self.h(r, j + 1)
|
|
2720
|
+
elif route == "value":
|
|
2721
|
+
rd[j] = hs[j] + 1 # 2h+1 - h
|
|
2722
|
+
elif route == "reduction":
|
|
2723
|
+
rd[j] = None
|
|
2724
|
+
elif dr:
|
|
2725
|
+
rd[j] = hs[j]
|
|
2726
|
+
if da:
|
|
2727
|
+
if after == "same":
|
|
2728
|
+
aft[j] = hs[j]
|
|
2729
|
+
elif after == "write":
|
|
2730
|
+
base = self.h(r, j + 1) if route in ("from", "copyout") \
|
|
2731
|
+
else hs[j]
|
|
2732
|
+
aft[j] = 2 * base + 1
|
|
2733
|
+
elif after == "red":
|
|
2734
|
+
aft[j] = hs[j] + 4 * (j + 1)
|
|
2735
|
+
return rd, aft
|
|
2736
|
+
|
|
2737
|
+
def body(self):
|
|
2738
|
+
ind = " "
|
|
2739
|
+
lines = [f"{ind}cs = 0"]
|
|
2740
|
+
for r, route in enumerate(self.p["routes"]):
|
|
2741
|
+
lines += self.route_lines(r, route)
|
|
2742
|
+
rd, aft = self.expect(r, route)
|
|
2743
|
+
S = self.names(r, route)
|
|
2744
|
+
for j, s in enumerate(S, 1):
|
|
2745
|
+
if rd[j - 1] is not None:
|
|
2746
|
+
lines.append(f"{ind}cs = mod(cs * 31 + rd({j}), {P}_8)")
|
|
2747
|
+
else:
|
|
2748
|
+
lines.append(f"{ind}print '(a,i0,a,i0)', 'OBS "
|
|
2749
|
+
f"{self.name} {route} rd ', {j}, ' ', "
|
|
2750
|
+
f"rd({j})")
|
|
2751
|
+
if aft[j - 1] is not None:
|
|
2752
|
+
lines.append(f"{ind}cs = mod(cs * 31 + {s}, {P}_8)")
|
|
2753
|
+
else:
|
|
2754
|
+
lines.append(f"{ind}hv = {s}")
|
|
2755
|
+
lines.append(f"{ind}print '(a,i0,a,i0)', 'OBS "
|
|
2756
|
+
f"{self.name} {route} host ', {j}, ' ', hv")
|
|
2757
|
+
return lines
|
|
2758
|
+
|
|
2759
|
+
def value(self):
|
|
2760
|
+
cs = 0
|
|
2761
|
+
for r, route in enumerate(self.p["routes"]):
|
|
2762
|
+
rd, aft = self.expect(r, route)
|
|
2763
|
+
for j in range(self.p["nscal"]):
|
|
2764
|
+
if rd[j] is not None:
|
|
2765
|
+
cs = (cs * 31 + rd[j]) % P
|
|
2766
|
+
if aft[j] is not None:
|
|
2767
|
+
cs = (cs * 31 + aft[j]) % P
|
|
2768
|
+
return cs
|
|
2769
|
+
|
|
2770
|
+
def smaller(self):
|
|
2771
|
+
rs = self.p["routes"]
|
|
2772
|
+
out = []
|
|
2773
|
+
if len(rs) > 1:
|
|
2774
|
+
h = len(rs) // 2
|
|
2775
|
+
out += [self.clone(routes=rs[:h]), self.clone(routes=rs[h:])]
|
|
2776
|
+
if self.p["nscal"] > 1:
|
|
2777
|
+
out.append(self.clone(nscal=1))
|
|
2778
|
+
return out
|
|
2779
|
+
|
|
2780
|
+
def features(self):
|
|
2781
|
+
return super().features() | {f"route:{r}" for r in self.p["routes"]}
|
|
2782
|
+
|
|
2783
|
+
|
|
2784
|
+
# --- reductions + atomics + criticals, expressions, async, runtime -----------------------------
|
|
2785
|
+
|
|
2786
|
+
class MixedKernel(Kernel):
|
|
2787
|
+
"""`nred` reduction variables (cycling operators), `natom` counters
|
|
2788
|
+
updated by atomic update, a histogram updated in `ncrit` named critical
|
|
2789
|
+
sections (OpenMP: in a target parallel do, no teams: Ruling of
|
|
2790
|
+
offload.engine.fuzz on critical and teams), all in one loop. OpenACC: the
|
|
2791
|
+
reductions and atomics (OpenACC has no critical)."""
|
|
2792
|
+
kind = "mixed"
|
|
2793
|
+
|
|
2794
|
+
def draw(self, rng):
|
|
2795
|
+
self.p.setdefault("nred", 4)
|
|
2796
|
+
self.p.setdefault("natom", 2)
|
|
2797
|
+
self.p.setdefault("ncrit", 2 if self.o.model == "omp" else 0)
|
|
2798
|
+
self.p.setdefault("n", 512)
|
|
2799
|
+
|
|
2800
|
+
def decls(self):
|
|
2801
|
+
nr, na, nc = self.p["nred"], self.p["natom"], self.p["ncrit"]
|
|
2802
|
+
d = ["integer :: i", f"integer(8) :: hist({max(1, nc)}, 8)"]
|
|
2803
|
+
if nr:
|
|
2804
|
+
d += decl_lines("integer(8)", [vname("r", j) for j in
|
|
2805
|
+
range(1, nr + 1)], self.o.width)
|
|
2806
|
+
if na:
|
|
2807
|
+
d += decl_lines("integer(8)", [vname("q", j) for j in
|
|
2808
|
+
range(1, na + 1)], self.o.width)
|
|
2809
|
+
return d
|
|
2810
|
+
|
|
2811
|
+
def body(self):
|
|
2812
|
+
nr, na, nc, n = (self.p["nred"], self.p["natom"], self.p["ncrit"],
|
|
2813
|
+
self.p["n"])
|
|
2814
|
+
o = self.o
|
|
2815
|
+
ind = " "
|
|
2816
|
+
R = [vname("r", j) for j in range(1, nr + 1)]
|
|
2817
|
+
Q = [vname("q", j) for j in range(1, na + 1)]
|
|
2818
|
+
ops = [("+", "max", "ieor", "ior")[j % 4] for j in range(nr)]
|
|
2819
|
+
lines = [f"{ind}{x} = 0" for x in R + Q] + [f"{ind}hist = 0"]
|
|
2820
|
+
groups: dict[str, list[str]] = {}
|
|
2821
|
+
for x, op in zip(R, ops):
|
|
2822
|
+
groups.setdefault(op, []).append(x)
|
|
2823
|
+
red = [(op, groups[op]) for op in ("+", "max", "ieor", "ior")
|
|
2824
|
+
if op in groups]
|
|
2825
|
+
chain = ("target parallel do",) if o.model == "omp" else \
|
|
2826
|
+
("parallel loop gang vector",)
|
|
2827
|
+
op_, cl, ii = region(o, chain, ind, reduction=red,
|
|
2828
|
+
data=[(x, "tofrom") for x in Q] +
|
|
2829
|
+
[("hist", "tofrom")])
|
|
2830
|
+
lines += op_ + [f"{ii}do i = 1, {n}"]
|
|
2831
|
+
for j, (x, op) in enumerate(zip(R, ops)):
|
|
2832
|
+
e = f"int(mod(i * {j + 3}, 4099), 8)"
|
|
2833
|
+
lines.append(f"{ii} {x} = " + {
|
|
2834
|
+
"+": f"{x} + {e}", "max": f"max({x}, {e})",
|
|
2835
|
+
"ieor": f"ieor({x}, {e})",
|
|
2836
|
+
"ior": f"ior({x}, {e})"}[op])
|
|
2837
|
+
for j, x in enumerate(Q):
|
|
2838
|
+
lines += [f"{ii} {o.sent} atomic update",
|
|
2839
|
+
f"{ii} {x} = {x} + mod(i, {j + 2})"]
|
|
2840
|
+
for c in range(1, nc + 1):
|
|
2841
|
+
lines += [f"{ii} {o.sent} critical (c{self.name}_{c})",
|
|
2842
|
+
f"{ii} hist({c}, mod(i, 8) + 1) = "
|
|
2843
|
+
f"hist({c}, mod(i, 8) + 1) + {c}",
|
|
2844
|
+
f"{ii} {o.sent} end critical (c{self.name}_{c})"]
|
|
2845
|
+
lines += [f"{ii}end do"] + cl
|
|
2846
|
+
lines.append(f"{ind}call st_cksum(hist, {max(1, nc) * 8}, cs)")
|
|
2847
|
+
for x in R + Q:
|
|
2848
|
+
lines.append(f"{ind}cs = mod(cs * 31 + {x}, {P}_8)")
|
|
2849
|
+
return lines
|
|
2850
|
+
|
|
2851
|
+
def value(self):
|
|
2852
|
+
nr, na, nc, n = (self.p["nred"], self.p["natom"], self.p["ncrit"],
|
|
2853
|
+
self.p["n"])
|
|
2854
|
+
hist = [[0] * 8 for _ in range(max(1, nc))]
|
|
2855
|
+
for c in range(1, nc + 1):
|
|
2856
|
+
for i in range(1, n + 1):
|
|
2857
|
+
hist[c - 1][i % 8] += c
|
|
2858
|
+
flat = [hist[c][b] for b in range(8) for c in range(max(1, nc))]
|
|
2859
|
+
cs = cksum(flat)
|
|
2860
|
+
ops = [("+", "max", "ieor", "ior")[j % 4] for j in range(nr)]
|
|
2861
|
+
for j, op in enumerate(ops):
|
|
2862
|
+
v = 0
|
|
2863
|
+
for i in range(1, n + 1):
|
|
2864
|
+
e = (i * (j + 3)) % 4099
|
|
2865
|
+
v = {"+": v + e, "max": max(v, e), "ieor": v ^ e,
|
|
2866
|
+
"ior": v | e}[op]
|
|
2867
|
+
cs = (cs * 31 + v) % P
|
|
2868
|
+
for j in range(na):
|
|
2869
|
+
cs = (cs * 31 + sum(i % (j + 2) for i in range(1, n + 1))) % P
|
|
2870
|
+
return cs
|
|
2871
|
+
|
|
2872
|
+
def smaller(self):
|
|
2873
|
+
out = []
|
|
2874
|
+
for key in ("nred", "natom", "ncrit"):
|
|
2875
|
+
if self.p[key] > 0:
|
|
2876
|
+
out.append(self.clone(**{key: self.p[key] // 2}))
|
|
2877
|
+
return out
|
|
2878
|
+
|
|
2879
|
+
def features(self):
|
|
2880
|
+
f = super().features() | {f"len:mixed:{self.p['nred']}"}
|
|
2881
|
+
if self.p["natom"]:
|
|
2882
|
+
f.add("dir:atomic")
|
|
2883
|
+
if self.p["ncrit"]:
|
|
2884
|
+
f.add("dir:critical")
|
|
2885
|
+
return f
|
|
2886
|
+
|
|
2887
|
+
|
|
2888
|
+
class ExprsKernel(Kernel):
|
|
2889
|
+
"""Compile-time stress in device code: 'expr', one assignment of
|
|
2890
|
+
`size` terms (continuation lines: past 255 an illegal probe); 'select',
|
|
2891
|
+
a SELECT CASE of `size` cases in a device function; 'spec', `size`
|
|
2892
|
+
device functions (specializations) dispatched by a SELECT CASE."""
|
|
2893
|
+
kind = "exprs"
|
|
2894
|
+
|
|
2895
|
+
def draw(self, rng):
|
|
2896
|
+
self.p.setdefault("variant", rng.choice(("expr", "select", "spec")))
|
|
2897
|
+
self.p.setdefault("size", 64)
|
|
2898
|
+
self.p.setdefault("n", 256)
|
|
2899
|
+
|
|
2900
|
+
def modules(self):
|
|
2901
|
+
v, k = self.p["variant"], self.p["size"]
|
|
2902
|
+
dt = _dt_line(self.o)
|
|
2903
|
+
cont = []
|
|
2904
|
+
if v == "select":
|
|
2905
|
+
cont += [f" function {self.name}_sel(x) result(r)", dt,
|
|
2906
|
+
" integer(8), intent(in) :: x", " integer(8) :: r",
|
|
2907
|
+
f" select case (mod(x, {k}_8))"]
|
|
2908
|
+
for c in range(k):
|
|
2909
|
+
cont += [f" case ({c})", f" r = x * {c % 17 + 1} + "
|
|
2910
|
+
f"{c}"]
|
|
2911
|
+
cont += [" case default", " r = -1", " end select",
|
|
2912
|
+
f" end function {self.name}_sel"]
|
|
2913
|
+
if v == "spec":
|
|
2914
|
+
for c in range(k):
|
|
2915
|
+
cont += [f" function {self.name}_s{c}(x) result(r)", dt,
|
|
2916
|
+
" integer(8), intent(in) :: x",
|
|
2917
|
+
" integer(8) :: r",
|
|
2918
|
+
f" r = x * {c % 17 + 1} + {c}",
|
|
2919
|
+
f" end function {self.name}_s{c}"]
|
|
2920
|
+
cont += [f" function {self.name}_sel(x) result(r)", dt,
|
|
2921
|
+
" integer(8), intent(in) :: x", " integer(8) :: r",
|
|
2922
|
+
f" select case (mod(x, {k}_8))"]
|
|
2923
|
+
for c in range(k):
|
|
2924
|
+
cont += [f" case ({c})", f" r = {self.name}_s{c}(x)"]
|
|
2925
|
+
cont += [" case default", " r = -1", " end select",
|
|
2926
|
+
f" end function {self.name}_sel"]
|
|
2927
|
+
return [Module(f"{self.name}_m", [], cont)] if cont else []
|
|
2928
|
+
|
|
2929
|
+
def uses(self):
|
|
2930
|
+
return [f"{self.name}_m"] if self.p["variant"] != "expr" else []
|
|
2931
|
+
|
|
2932
|
+
def decls(self):
|
|
2933
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i"]
|
|
2934
|
+
|
|
2935
|
+
def body(self):
|
|
2936
|
+
v, k, n = self.p["variant"], self.p["size"], self.p["n"]
|
|
2937
|
+
ind = " "
|
|
2938
|
+
chain = ("target teams distribute parallel do",) if \
|
|
2939
|
+
self.o.model == "omp" else ("parallel loop gang vector",)
|
|
2940
|
+
op, cl, ii = region(self.o, chain, ind, data=[("out", "tofrom")])
|
|
2941
|
+
lines = [f"{ind}out = 0"] + op + [f"{ii}do i = 1, {n}"]
|
|
2942
|
+
if v == "expr":
|
|
2943
|
+
terms = [f"mod(i * {c % 97 + 1}, {c % 13 + 2})"
|
|
2944
|
+
for c in range(k)]
|
|
2945
|
+
lines += pack("out(i) =", [t + (" +" if c < k - 1 else "")
|
|
2946
|
+
for c, t in enumerate(terms)],
|
|
2947
|
+
ii + " ", None, self.o.width)
|
|
2948
|
+
else:
|
|
2949
|
+
lines.append(f"{ii} out(i) = {self.name}_sel(int(i, 8))")
|
|
2950
|
+
lines += [f"{ii}end do"] + cl
|
|
2951
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
2952
|
+
return lines
|
|
2953
|
+
|
|
2954
|
+
def value(self):
|
|
2955
|
+
v, k, n = self.p["variant"], self.p["size"], self.p["n"]
|
|
2956
|
+
if v == "expr":
|
|
2957
|
+
return cksum(sum((i * (c % 97 + 1)) % (c % 13 + 2)
|
|
2958
|
+
for c in range(k)) for i in range(1, n + 1))
|
|
2959
|
+
return cksum(i * ((i % k) % 17 + 1) + (i % k)
|
|
2960
|
+
for i in range(1, n + 1))
|
|
2961
|
+
|
|
2962
|
+
def smaller(self):
|
|
2963
|
+
return [self.clone(size=m) for m in _halve(self.p["size"])]
|
|
2964
|
+
|
|
2965
|
+
def features(self):
|
|
2966
|
+
return super().features() | {f"exprs:{self.p['variant']}",
|
|
2967
|
+
f"len:exprs:{self.p['size']}"}
|
|
2968
|
+
|
|
2969
|
+
|
|
2970
|
+
class AsyncKernel(Kernel):
|
|
2971
|
+
"""`ntasks` concurrent target tasks: each enters its own array (target
|
|
2972
|
+
enter data nowait depend(out:)), a target nowait depend(inout:)
|
|
2973
|
+
computes, the host updates another array, target update from nowait
|
|
2974
|
+
depend(in:) brings it back; one taskwait. OpenACC: the same over
|
|
2975
|
+
`ntasks` async queues (enter data async, parallel loop async, update
|
|
2976
|
+
self async) and one wait."""
|
|
2977
|
+
kind = "async"
|
|
2978
|
+
|
|
2979
|
+
def draw(self, rng):
|
|
2980
|
+
self.p.setdefault("ntasks", 8)
|
|
2981
|
+
self.p.setdefault("m", 64)
|
|
2982
|
+
|
|
2983
|
+
def decls(self):
|
|
2984
|
+
k, m = self.p["ntasks"], self.p["m"]
|
|
2985
|
+
return [f"integer(8) :: x({m}, {k}), h({m}, {k})",
|
|
2986
|
+
"integer :: i, t", "integer(8) :: tcs"]
|
|
2987
|
+
|
|
2988
|
+
def body(self):
|
|
2989
|
+
k, m = self.p["ntasks"], self.p["m"]
|
|
2990
|
+
o = self.o
|
|
2991
|
+
ind = " "
|
|
2992
|
+
lines = [f"{ind}do t = 1, {k}", f"{ind} do i = 1, {m}",
|
|
2993
|
+
f"{ind} x(i, t) = i + t", f"{ind} h(i, t) = 0",
|
|
2994
|
+
f"{ind} end do", f"{ind}end do"]
|
|
2995
|
+
if o.model == "omp":
|
|
2996
|
+
lines += [f"{ind}do t = 1, {k}",
|
|
2997
|
+
f"{ind} {o.sent} target enter data map(to: x(:, t)) "
|
|
2998
|
+
"nowait depend(out: x(:, t))",
|
|
2999
|
+
f"{ind} {o.sent} target teams distribute parallel do "
|
|
3000
|
+
"nowait depend(inout: x(:, t))",
|
|
3001
|
+
f"{ind} do i = 1, {m}",
|
|
3002
|
+
f"{ind} x(i, t) = x(i, t) * 3 + t",
|
|
3003
|
+
f"{ind} end do",
|
|
3004
|
+
f"{ind} {o.sent} end target teams distribute parallel "
|
|
3005
|
+
"do",
|
|
3006
|
+
f"{ind} {o.sent} target exit data map(from: x(:, t)) "
|
|
3007
|
+
"nowait depend(inout: x(:, t))",
|
|
3008
|
+
f"{ind} do i = 1, {m}", f"{ind} h(i, t) = i * t",
|
|
3009
|
+
f"{ind} end do",
|
|
3010
|
+
f"{ind}end do", f"{ind}{o.sent} taskwait"]
|
|
3011
|
+
else:
|
|
3012
|
+
lines += [f"{ind}do t = 1, {k}",
|
|
3013
|
+
f"{ind} {o.sent} enter data copyin(x(:, t)) async(t)",
|
|
3014
|
+
f"{ind} {o.sent} parallel loop present(x(:, t)) "
|
|
3015
|
+
"async(t)",
|
|
3016
|
+
f"{ind} do i = 1, {m}",
|
|
3017
|
+
f"{ind} x(i, t) = x(i, t) * 3 + t",
|
|
3018
|
+
f"{ind} end do",
|
|
3019
|
+
f"{ind} {o.sent} exit data copyout(x(:, t)) async(t)",
|
|
3020
|
+
f"{ind} do i = 1, {m}", f"{ind} h(i, t) = i * t",
|
|
3021
|
+
f"{ind} end do",
|
|
3022
|
+
f"{ind}end do", f"{ind}{o.sent} wait"]
|
|
3023
|
+
lines += [f"{ind}cs = 0", f"{ind}do t = 1, {k}",
|
|
3024
|
+
f"{ind} call st_cksum(x(:, t), {m}, tcs)",
|
|
3025
|
+
f"{ind} cs = mod(cs * 31 + tcs, {P}_8)",
|
|
3026
|
+
f"{ind} call st_cksum(h(:, t), {m}, tcs)",
|
|
3027
|
+
f"{ind} cs = mod(cs * 31 + tcs, {P}_8)", f"{ind}end do"]
|
|
3028
|
+
return lines
|
|
3029
|
+
|
|
3030
|
+
def value(self):
|
|
3031
|
+
k, m = self.p["ntasks"], self.p["m"]
|
|
3032
|
+
cs = 0
|
|
3033
|
+
for t in range(1, k + 1):
|
|
3034
|
+
cs = (cs * 31 + cksum((i + t) * 3 + t for i in range(1, m + 1))) \
|
|
3035
|
+
% P
|
|
3036
|
+
cs = (cs * 31 + cksum(i * t for i in range(1, m + 1))) % P
|
|
3037
|
+
return cs
|
|
3038
|
+
|
|
3039
|
+
def smaller(self):
|
|
3040
|
+
return [self.clone(ntasks=x) for x in _halve(self.p["ntasks"])]
|
|
3041
|
+
|
|
3042
|
+
def features(self):
|
|
3043
|
+
return super().features() | {f"len:async:{self.p['ntasks']}"}
|
|
3044
|
+
|
|
3045
|
+
|
|
3046
|
+
class RuntimeKernel(Kernel):
|
|
3047
|
+
"""Runtime stress: 'iters', a reduction over `size` iterations of
|
|
3048
|
+
mod(i*c, 1009) (the model uses its period); 'teams', num_teams(size)
|
|
3049
|
+
thread_limit(t) over `size`*t iterations; 'alloc', an allocatable of
|
|
3050
|
+
`size` 8-byte elements (bounded: the size is in the header) filled and
|
|
3051
|
+
reduced on the device."""
|
|
3052
|
+
kind = "runtime"
|
|
3053
|
+
|
|
3054
|
+
def draw(self, rng):
|
|
3055
|
+
self.p.setdefault("variant", "iters")
|
|
3056
|
+
self.p.setdefault("size", 1 << 20)
|
|
3057
|
+
self.p.setdefault("c", rng.randrange(1, 1009))
|
|
3058
|
+
|
|
3059
|
+
def decls(self):
|
|
3060
|
+
d = ["integer(8) :: i, nn, s"]
|
|
3061
|
+
if self.p["variant"] == "alloc":
|
|
3062
|
+
d.append("integer(8), allocatable :: big(:)")
|
|
3063
|
+
return d
|
|
3064
|
+
|
|
3065
|
+
def iters(self):
|
|
3066
|
+
if self.p["variant"] == "teams":
|
|
3067
|
+
return self.p["size"] * 256
|
|
3068
|
+
return self.p["size"]
|
|
3069
|
+
|
|
3070
|
+
def body(self):
|
|
3071
|
+
v, c = self.p["variant"], self.p["c"]
|
|
3072
|
+
o = self.o
|
|
3073
|
+
ind = " "
|
|
3074
|
+
nn = self.iters()
|
|
3075
|
+
lines = [f"{ind}nn = {nn}_8", f"{ind}s = 0"]
|
|
3076
|
+
if v == "alloc":
|
|
3077
|
+
lines.append(f"{ind}allocate(big(nn))")
|
|
3078
|
+
if o.model == "omp":
|
|
3079
|
+
lines += [f"{ind}{o.sent} target enter data map(alloc: big)"]
|
|
3080
|
+
op, cl, ii = region(o, ("target teams distribute parallel "
|
|
3081
|
+
"do",), ind)
|
|
3082
|
+
else:
|
|
3083
|
+
lines += [f"{ind}{o.sent} enter data create(big)"]
|
|
3084
|
+
op, cl, ii = region(o, ("parallel loop gang vector",), ind,
|
|
3085
|
+
extra=["present(big)"])
|
|
3086
|
+
lines += op + [f"{ii}do i = 1, nn",
|
|
3087
|
+
f"{ii} big(i) = mod(i * {c}, 1009_8)",
|
|
3088
|
+
f"{ii}end do"] + cl
|
|
3089
|
+
op, cl, ii = region(o, ("target teams distribute parallel do",)
|
|
3090
|
+
if o.model == "omp" else
|
|
3091
|
+
("parallel loop gang vector",), ind,
|
|
3092
|
+
reduction=[("+", ["s"])],
|
|
3093
|
+
extra=["present(big)"] if o.model == "acc"
|
|
3094
|
+
else [])
|
|
3095
|
+
lines += op + [f"{ii}do i = 1, nn", f"{ii} s = s + big(i)",
|
|
3096
|
+
f"{ii}end do"] + cl
|
|
3097
|
+
lines.append(f"{ind}{o.sent} target exit data map(delete: big)"
|
|
3098
|
+
if o.model == "omp" else
|
|
3099
|
+
f"{ind}{o.sent} exit data delete(big)")
|
|
3100
|
+
lines.append(f"{ind}deallocate(big)")
|
|
3101
|
+
else:
|
|
3102
|
+
extra = []
|
|
3103
|
+
if v == "teams" and o.model == "omp":
|
|
3104
|
+
extra = [f"num_teams({self.p['size']})",
|
|
3105
|
+
"thread_limit(256)"]
|
|
3106
|
+
if v == "teams" and o.model == "acc":
|
|
3107
|
+
extra = [f"num_gangs({self.p['size']})", "vector_length(256)"]
|
|
3108
|
+
chain = ("target teams distribute parallel do",) if \
|
|
3109
|
+
o.model == "omp" else ("parallel loop gang vector",)
|
|
3110
|
+
op, cl, ii = region(o, chain, ind, reduction=[("+", ["s"])],
|
|
3111
|
+
extra=extra)
|
|
3112
|
+
lines += op + [f"{ii}do i = 1, nn",
|
|
3113
|
+
f"{ii} s = s + mod(i * {c}, 1009_8)",
|
|
3114
|
+
f"{ii}end do"] + cl
|
|
3115
|
+
lines.append(f"{ind}cs = mod(s, {P}_8)")
|
|
3116
|
+
return lines
|
|
3117
|
+
|
|
3118
|
+
def value(self):
|
|
3119
|
+
c, nn = self.p["c"], self.iters()
|
|
3120
|
+
per = sum((i * c) % 1009 for i in range(1009))
|
|
3121
|
+
q, r = divmod(nn, 1009)
|
|
3122
|
+
s = q * per + sum((i * c) % 1009 for i in range(1, r + 1))
|
|
3123
|
+
# i runs 1..nn: the block 1..1009 has the same sum as 0..1008
|
|
3124
|
+
return s % P
|
|
3125
|
+
|
|
3126
|
+
def smaller(self):
|
|
3127
|
+
return [self.clone(size=max(1, self.p["size"] // 16))] if \
|
|
3128
|
+
self.p["size"] > 16 else []
|
|
3129
|
+
|
|
3130
|
+
def features(self):
|
|
3131
|
+
return super().features() | {f"runtime:{self.p['variant']}"}
|
|
3132
|
+
|
|
3133
|
+
def bytes(self) -> int:
|
|
3134
|
+
return 8 * self.iters() if self.p["variant"] == "alloc" else 0
|
|
3135
|
+
|
|
3136
|
+
|
|
3137
|
+
# --- templates: shapes of failing real kernels ----------------------------------------------------
|
|
3138
|
+
|
|
3139
|
+
TEMPLATES = ("team_private", "declared_alloc", "mfc_cbc", "mfc_bubbles")
|
|
3140
|
+
|
|
3141
|
+
|
|
3142
|
+
class TemplateKernel(Kernel):
|
|
3143
|
+
"""Kernel shapes of failing real kernels (structure only), varied:
|
|
3144
|
+
|
|
3145
|
+
* team_private: an array private to each team (teams distribute
|
|
3146
|
+
private(t)) written and read by nested parallel loops (the
|
|
3147
|
+
widened program teams-private-array-parallel: AFAR and every CCE
|
|
3148
|
+
wrong; PRK transpose tile32 has the same shape with collapse(2) and
|
|
3149
|
+
simd); `w` tile width, `nloops` nested loops, collapse / simd;
|
|
3150
|
+
* declared_alloc: a declare target module variable of a derived type
|
|
3151
|
+
with `ncomp` allocatable components entered by enter data (MFC under CCE at unified memory);
|
|
3152
|
+
* mfc_cbc: MFC's s_cbc kernel (m_cbc.fpp:597, CCE 20 device-link
|
|
3153
|
+
crash): collapse(2), a long private list of scalars and private
|
|
3154
|
+
arrays (`npriv` extra scalars), loop bounds from components of a
|
|
3155
|
+
device-resident module derived type, inner sequential loops, device
|
|
3156
|
+
routines with array arguments, a module logical branch;
|
|
3157
|
+
* mfc_bubbles: MFC's s_compute_bubble_EE_source (m_bubbles_EE.fpp:186,
|
|
3158
|
+
CCE 21 device-link crash): an array of derived type with a pointer (or
|
|
3159
|
+
allocatable) 3-D component indexed through integer index arrays,
|
|
3160
|
+
collapse(3), private arrays, a device function with an OPTIONAL
|
|
3161
|
+
argument passed by keyword, a counter updated atomically."""
|
|
3162
|
+
kind = "template"
|
|
3163
|
+
|
|
3164
|
+
def draw(self, rng):
|
|
3165
|
+
v = self.p.setdefault("variant", rng.choice(TEMPLATES))
|
|
3166
|
+
if v == "team_private":
|
|
3167
|
+
self.p.setdefault("w", rng.choice((4, 8, 32)))
|
|
3168
|
+
self.p.setdefault("nt", 16)
|
|
3169
|
+
self.p.setdefault("nloops", 2)
|
|
3170
|
+
self.p.setdefault("col2", rng.random() < 0.5)
|
|
3171
|
+
self.p.setdefault("simd", rng.random() < 0.5)
|
|
3172
|
+
elif v == "declared_alloc":
|
|
3173
|
+
self.p.setdefault("ncomp", 2)
|
|
3174
|
+
self.p.setdefault("n", 64)
|
|
3175
|
+
elif v == "mfc_cbc":
|
|
3176
|
+
self.p.setdefault("npriv", 40)
|
|
3177
|
+
self.p.setdefault("nf", 3)
|
|
3178
|
+
self.p.setdefault("nk", 6)
|
|
3179
|
+
self.p.setdefault("nr", 5)
|
|
3180
|
+
else:
|
|
3181
|
+
self.p.setdefault("nb", 3)
|
|
3182
|
+
self.p.setdefault("ext", [4, 3, 2])
|
|
3183
|
+
self.p.setdefault("ptr", rng.random() < 0.5)
|
|
3184
|
+
|
|
3185
|
+
# team_private ------------------------------------------------------------
|
|
3186
|
+
def _tp_body(self):
|
|
3187
|
+
w, nt, nl = self.p["w"], self.p["nt"], self.p["nloops"]
|
|
3188
|
+
col2, simd = self.p["col2"], self.p["simd"]
|
|
3189
|
+
o = self.o
|
|
3190
|
+
ind = " "
|
|
3191
|
+
n = w * nt
|
|
3192
|
+
lines = [f"{ind}do i = 1, {n}", f"{ind} a(i) = mod(i * 7, 61)",
|
|
3193
|
+
f"{ind}end do", f"{ind}b = 0"]
|
|
3194
|
+
inner = "parallel do simd" if simd else "parallel do"
|
|
3195
|
+
if o.model == "acc":
|
|
3196
|
+
return self._tp_body_acc(lines, n)
|
|
3197
|
+
if col2:
|
|
3198
|
+
# 2-D tiles: n = (w*nt) elements as (w, nt) blocks of a 2-D view
|
|
3199
|
+
head = pack("target teams distribute collapse(2)",
|
|
3200
|
+
["private(t, j, jj)", "map(to: a)", "map(tofrom: b)"],
|
|
3201
|
+
ind, o.sent, o.width)
|
|
3202
|
+
lines += head + [f"{ind}do jt = 1, {nt}, 2", f"{ind} do kt = 0, 1"]
|
|
3203
|
+
ii = ind + " "
|
|
3204
|
+
lines += [f"{ii}{o.sent} {inner} collapse(2)",
|
|
3205
|
+
f"{ii}do j = 0, {w - 1}", f"{ii} do jj = 0, 0",
|
|
3206
|
+
f"{ii} t(j) = a((jt + kt - 1) * {w} + j + 1)",
|
|
3207
|
+
f"{ii} end do", f"{ii}end do",
|
|
3208
|
+
f"{ii}{o.sent} end {inner}"]
|
|
3209
|
+
for L in range(1, nl):
|
|
3210
|
+
lines += [f"{ii}{o.sent} {inner} collapse(2)",
|
|
3211
|
+
f"{ii}do j = 0, {w - 1}", f"{ii} do jj = 0, 0",
|
|
3212
|
+
f"{ii} b((jt + kt - 1) * {w} + j + 1) = "
|
|
3213
|
+
f"b((jt + kt - 1) * {w} + j + 1) + "
|
|
3214
|
+
f"{L + 1} * t({w - 1} - j) + {L}",
|
|
3215
|
+
f"{ii} end do", f"{ii}end do",
|
|
3216
|
+
f"{ii}{o.sent} end {inner}"]
|
|
3217
|
+
lines += [f"{ind} end do", f"{ind}end do",
|
|
3218
|
+
f"{ind}{o.sent} end target teams distribute"]
|
|
3219
|
+
else:
|
|
3220
|
+
head = pack("target teams distribute",
|
|
3221
|
+
["private(t, j)", "map(to: a)", "map(tofrom: b)"],
|
|
3222
|
+
ind, o.sent, o.width)
|
|
3223
|
+
lines += head + [f"{ind}do jt = 1, {n}, {w}"]
|
|
3224
|
+
ii = ind + " "
|
|
3225
|
+
lines += [f"{ii}{o.sent} {inner}", f"{ii}do j = 0, {w - 1}",
|
|
3226
|
+
f"{ii} t(j) = a(jt + j)", f"{ii}end do",
|
|
3227
|
+
f"{ii}{o.sent} end {inner}"]
|
|
3228
|
+
for L in range(1, nl):
|
|
3229
|
+
lines += [f"{ii}{o.sent} {inner}", f"{ii}do j = 0, {w - 1}",
|
|
3230
|
+
f"{ii} b(jt + j) = b(jt + j) + {L + 1} * "
|
|
3231
|
+
f"t({w - 1} - j) + {L}", f"{ii}end do",
|
|
3232
|
+
f"{ii}{o.sent} end {inner}"]
|
|
3233
|
+
lines += [f"{ind}end do", f"{ind}{o.sent} end target teams "
|
|
3234
|
+
"distribute"]
|
|
3235
|
+
lines.append(f"{ind}call st_cksum(b, {n}, cs)")
|
|
3236
|
+
return lines
|
|
3237
|
+
|
|
3238
|
+
def _tp_body_acc(self, lines, n):
|
|
3239
|
+
w, nt, nl = self.p["w"], self.p["nt"], self.p["nloops"]
|
|
3240
|
+
o = self.o
|
|
3241
|
+
ind = " "
|
|
3242
|
+
lines += pack("parallel loop gang", ["private(t)", "copyin(a)",
|
|
3243
|
+
"copy(b)"], ind, o.sent, o.width)
|
|
3244
|
+
lines += [f"{ind}do jt = 1, {n}, {w}"]
|
|
3245
|
+
ii = ind + " "
|
|
3246
|
+
lines += [f"{ii}{o.sent} loop vector", f"{ii}do j = 0, {w - 1}",
|
|
3247
|
+
f"{ii} t(j) = a(jt + j)", f"{ii}end do"]
|
|
3248
|
+
for L in range(1, nl):
|
|
3249
|
+
lines += [f"{ii}{o.sent} loop vector", f"{ii}do j = 0, {w - 1}",
|
|
3250
|
+
f"{ii} b(jt + j) = b(jt + j) + {L + 1} * "
|
|
3251
|
+
f"t({w - 1} - j) + {L}", f"{ii}end do"]
|
|
3252
|
+
lines += [f"{ind}end do", f"{ind}{o.sent} end parallel loop"]
|
|
3253
|
+
lines.append(f"{ind}call st_cksum(b, {n}, cs)")
|
|
3254
|
+
return lines
|
|
3255
|
+
|
|
3256
|
+
def _tp_value(self):
|
|
3257
|
+
w, nt, nl = self.p["w"], self.p["nt"], self.p["nloops"]
|
|
3258
|
+
n = w * nt
|
|
3259
|
+
a = [0] + [(i * 7) % 61 for i in range(1, n + 1)]
|
|
3260
|
+
b = [0] * (n + 1)
|
|
3261
|
+
for blk in range(nt):
|
|
3262
|
+
base = blk * w
|
|
3263
|
+
t = [a[base + j + 1] for j in range(w)]
|
|
3264
|
+
for L in range(1, nl):
|
|
3265
|
+
for j in range(w):
|
|
3266
|
+
b[base + j + 1] += (L + 1) * t[w - 1 - j] + L
|
|
3267
|
+
return cksum(b[1:])
|
|
3268
|
+
|
|
3269
|
+
# declared_alloc -----------------------------------------------------------
|
|
3270
|
+
def _da_modules(self):
|
|
3271
|
+
k = self.p["ncomp"]
|
|
3272
|
+
o = self.o
|
|
3273
|
+
spec = [f"type :: {self.name}_rec"] + [
|
|
3274
|
+
f" integer(8), allocatable :: v{c}(:)" for c in range(1, k + 1)
|
|
3275
|
+
] + [f"end type {self.name}_rec", f"type({self.name}_rec) :: gq"]
|
|
3276
|
+
spec.append(f"{o.sent} declare target(gq)" if o.model == "omp" else
|
|
3277
|
+
f"{o.sent} declare create(gq)")
|
|
3278
|
+
return [Module(f"{self.name}_m", spec)]
|
|
3279
|
+
|
|
3280
|
+
def _da_body(self):
|
|
3281
|
+
k, n = self.p["ncomp"], self.p["n"]
|
|
3282
|
+
o = self.o
|
|
3283
|
+
ind = " "
|
|
3284
|
+
lines = []
|
|
3285
|
+
comps = [f"gq%v{c}" for c in range(1, k + 1)]
|
|
3286
|
+
for c, x in enumerate(comps, 1):
|
|
3287
|
+
lines += [f"{ind}allocate({x}({n}))", f"{ind}do i = 1, {n}",
|
|
3288
|
+
f"{ind} {x}(i) = i * {c + 2}", f"{ind}end do"]
|
|
3289
|
+
if o.model == "omp":
|
|
3290
|
+
lines += pack("target enter data", list_atoms("map", comps, "to"),
|
|
3291
|
+
ind, o.sent, o.width)
|
|
3292
|
+
else:
|
|
3293
|
+
lines += pack("enter data", list_atoms("copyin", comps), ind,
|
|
3294
|
+
o.sent, o.width)
|
|
3295
|
+
chain = ("target teams distribute parallel do",) if \
|
|
3296
|
+
o.model == "omp" else ("parallel loop",)
|
|
3297
|
+
op, cl, ii = region(o, chain, ind, data=[("out", "tofrom")])
|
|
3298
|
+
lines += [f"{ind}out = 0"] + op + [f"{ii}do i = 1, {n}"]
|
|
3299
|
+
lines += sum_lines(ii + " ", "out(i)", [f"{x}(i)" for x in comps],
|
|
3300
|
+
o.width)
|
|
3301
|
+
lines += [f"{ii} out(i) = out(i) + 1", f"{ii}end do"] + cl
|
|
3302
|
+
if o.model == "omp":
|
|
3303
|
+
lines += pack("target exit data", list_atoms("map", comps,
|
|
3304
|
+
"delete"),
|
|
3305
|
+
ind, o.sent, o.width)
|
|
3306
|
+
else:
|
|
3307
|
+
lines += pack("exit data", list_atoms("delete", comps), ind,
|
|
3308
|
+
o.sent, o.width)
|
|
3309
|
+
lines += [f"{ind}deallocate({x})" for x in comps]
|
|
3310
|
+
lines.append(f"{ind}call st_cksum(out, {n}, cs)")
|
|
3311
|
+
return lines
|
|
3312
|
+
|
|
3313
|
+
def _da_value(self):
|
|
3314
|
+
k, n = self.p["ncomp"], self.p["n"]
|
|
3315
|
+
return cksum(sum(i * (c + 2) for c in range(1, k + 1)) + 1
|
|
3316
|
+
for i in range(1, n + 1))
|
|
3317
|
+
|
|
3318
|
+
# mfc_cbc -------------------------------------------------------------------
|
|
3319
|
+
def _cbc_dims(self):
|
|
3320
|
+
nf = self.p["nf"]
|
|
3321
|
+
e = nf + 3 + 1
|
|
3322
|
+
return nf, e, e + nf # nf, eqn%e, nv
|
|
3323
|
+
|
|
3324
|
+
def _cbc_modules(self):
|
|
3325
|
+
o = self.o
|
|
3326
|
+
nm = self.name
|
|
3327
|
+
spec = [f"type :: {nm}_bnd", " integer :: beg, end",
|
|
3328
|
+
f"end type {nm}_bnd", f"type :: {nm}_eqn",
|
|
3329
|
+
f" type({nm}_bnd) :: cont, adv", " integer :: e",
|
|
3330
|
+
f"end type {nm}_eqn", f"type({nm}_eqn) :: eqn",
|
|
3331
|
+
"integer :: ndims", "logical :: chem"]
|
|
3332
|
+
spec.append(f"{o.sent} declare target(eqn, ndims, chem)"
|
|
3333
|
+
if o.model == "omp" else
|
|
3334
|
+
f"{o.sent} declare create(eqn, ndims, chem)")
|
|
3335
|
+
dt = _dt_line(o)
|
|
3336
|
+
cont = [f" subroutine {nm}_mix(rho, gam, ar, al, nf)", dt,
|
|
3337
|
+
" integer, intent(in) :: nf",
|
|
3338
|
+
" integer(8), intent(in) :: ar(nf), al(nf)",
|
|
3339
|
+
" integer(8), intent(out) :: rho, gam", " integer :: i",
|
|
3340
|
+
" rho = 0", " gam = 0", " do i = 1, nf",
|
|
3341
|
+
" rho = rho + ar(i)",
|
|
3342
|
+
" gam = mod(gam + al(i) * ar(i), 1009_8)", " end do",
|
|
3343
|
+
f" end subroutine {nm}_mix",
|
|
3344
|
+
f" subroutine {nm}_snd(pres, rho, gam, c)", dt,
|
|
3345
|
+
" integer(8), intent(in) :: pres, rho, gam",
|
|
3346
|
+
" integer(8), intent(out) :: c",
|
|
3347
|
+
" c = mod(pres * 3 + rho + gam, 10007_8)",
|
|
3348
|
+
f" end subroutine {nm}_snd"]
|
|
3349
|
+
return [Module(f"{nm}_m", spec, cont)]
|
|
3350
|
+
|
|
3351
|
+
def _cbc_privs(self):
|
|
3352
|
+
return [vname("x", j) for j in range(1, self.p["npriv"] + 1)]
|
|
3353
|
+
|
|
3354
|
+
def _cbc_body(self):
|
|
3355
|
+
nf, e, nv = self._cbc_dims()
|
|
3356
|
+
nk, nr = self.p["nk"], self.p["nr"]
|
|
3357
|
+
o = self.o
|
|
3358
|
+
nm = self.name
|
|
3359
|
+
ind = " "
|
|
3360
|
+
X = self._cbc_privs()
|
|
3361
|
+
lines = [f"{ind}eqn%cont%beg = 1", f"{ind}eqn%cont%end = {nf}",
|
|
3362
|
+
f"{ind}eqn%e = {e}", f"{ind}eqn%adv%beg = {e + 1}",
|
|
3363
|
+
f"{ind}eqn%adv%end = {e + nf}", f"{ind}ndims = 3",
|
|
3364
|
+
f"{ind}chem = .true."]
|
|
3365
|
+
lines.append(f"{ind}{o.sent} target update to(eqn, ndims, chem)"
|
|
3366
|
+
if o.model == "omp" else
|
|
3367
|
+
f"{ind}{o.sent} update device(eqn, ndims, chem)")
|
|
3368
|
+
lines += [f"{ind}allocate(q(0:2, {nk}, {nr}, {nv}))",
|
|
3369
|
+
f"{ind}do v = 1, {nv}", f"{ind} do r = 1, {nr}",
|
|
3370
|
+
f"{ind} do k = 1, {nk}", f"{ind} do b = 0, 2",
|
|
3371
|
+
f"{ind} q(b, k, r, v) = mod(b * 7 + k * 3 + r * 5 "
|
|
3372
|
+
"+ v, 101)",
|
|
3373
|
+
f"{ind} end do", f"{ind} end do", f"{ind} end do",
|
|
3374
|
+
f"{ind}end do", f"{ind}flux = 0", f"{ind}dir_idx = 2"]
|
|
3375
|
+
priv = ["r", "k", "i", "alpha_rho", "vel", "adv", "rho", "gam",
|
|
3376
|
+
"pres", "c", "accum"] + X
|
|
3377
|
+
if o.model == "omp":
|
|
3378
|
+
chain = ("target teams distribute parallel do",)
|
|
3379
|
+
data = [("q", "to"), ("flux", "tofrom"), ("dir_idx", "to")]
|
|
3380
|
+
else:
|
|
3381
|
+
chain = ("parallel loop gang vector",)
|
|
3382
|
+
data = [("q", "to"), ("flux", "tofrom"), ("dir_idx", "to")]
|
|
3383
|
+
op, cl, ii = region(o, chain, ind, data=data, private=priv,
|
|
3384
|
+
collapse=2)
|
|
3385
|
+
seq = [f"{o.sent} loop seq"] if o.model == "acc" else []
|
|
3386
|
+
lines += op + [f"{ii}do r = 1, {nr}", f"{ii} do k = 1, {nk}"]
|
|
3387
|
+
jj = ii + " "
|
|
3388
|
+
lines += [jj + s for s in seq] + [
|
|
3389
|
+
f"{jj}do i = 1, eqn%cont%end",
|
|
3390
|
+
f"{jj} alpha_rho(i) = q(0, k, r, i)", f"{jj}end do"]
|
|
3391
|
+
lines += [jj + s for s in seq] + [
|
|
3392
|
+
f"{jj}do i = 1, ndims",
|
|
3393
|
+
f"{jj} vel(i) = q(0, k, r, eqn%cont%end + i)", f"{jj}end do",
|
|
3394
|
+
f"{jj}pres = q(dir_idx - 2, k, r, eqn%e)"]
|
|
3395
|
+
lines += [jj + s for s in seq] + [
|
|
3396
|
+
f"{jj}do i = 1, eqn%adv%end - eqn%e",
|
|
3397
|
+
f"{jj} adv(i) = q(0, k, r, eqn%e + i)", f"{jj}end do",
|
|
3398
|
+
f"{jj}call {nm}_mix(rho, gam, alpha_rho, adv, eqn%cont%end)",
|
|
3399
|
+
f"{jj}if (chem) then", f"{jj} pres = pres + 7", f"{jj}end if",
|
|
3400
|
+
f"{jj}call {nm}_snd(pres, rho, gam, c)", f"{jj}accum = 0"]
|
|
3401
|
+
for j, x in enumerate(X, 1):
|
|
3402
|
+
lines.append(f"{jj}{x} = mod(c + {j} * k, 97_8)")
|
|
3403
|
+
lines += sum_lines(jj, "accum", X, o.width)
|
|
3404
|
+
lines += [f"{jj}flux(k, r) = c + vel(1) + vel(2) + vel(3) + accum",
|
|
3405
|
+
f"{ii} end do", f"{ii}end do"] + cl
|
|
3406
|
+
lines += [f"{ind}call st_cksum(flux, {nk * nr}, cs)",
|
|
3407
|
+
f"{ind}deallocate(q)"]
|
|
3408
|
+
return lines
|
|
3409
|
+
|
|
3410
|
+
def _cbc_value(self):
|
|
3411
|
+
nf, e, nv = self._cbc_dims()
|
|
3412
|
+
nk, nr = self.p["nk"], self.p["nr"]
|
|
3413
|
+
|
|
3414
|
+
def q(b, k, r, v):
|
|
3415
|
+
return (b * 7 + k * 3 + r * 5 + v) % 101
|
|
3416
|
+
flux = {}
|
|
3417
|
+
for r in range(1, nr + 1):
|
|
3418
|
+
for k in range(1, nk + 1):
|
|
3419
|
+
ar = [q(0, k, r, i) for i in range(1, nf + 1)]
|
|
3420
|
+
vel = [q(0, k, r, nf + i) for i in range(1, 4)]
|
|
3421
|
+
pres = q(0, k, r, e) + 7
|
|
3422
|
+
adv = [q(0, k, r, e + i) for i in range(1, nf + 1)]
|
|
3423
|
+
rho = sum(ar)
|
|
3424
|
+
gam = 0
|
|
3425
|
+
for i in range(nf):
|
|
3426
|
+
gam = (gam + adv[i] * ar[i]) % 1009
|
|
3427
|
+
c = (pres * 3 + rho + gam) % 10007
|
|
3428
|
+
acc = sum((c + j * k) % 97 for j in
|
|
3429
|
+
range(1, self.p["npriv"] + 1))
|
|
3430
|
+
flux[(k, r)] = c + sum(vel) + acc
|
|
3431
|
+
return cksum(flux[(k, r)] for r in range(1, nr + 1)
|
|
3432
|
+
for k in range(1, nk + 1))
|
|
3433
|
+
|
|
3434
|
+
# mfc_bubbles ---------------------------------------------------------------
|
|
3435
|
+
def _bub_modules(self):
|
|
3436
|
+
o = self.o
|
|
3437
|
+
nm = self.name
|
|
3438
|
+
attr = "pointer" if self.p["ptr"] else "allocatable"
|
|
3439
|
+
init = " => null()" if self.p["ptr"] else ""
|
|
3440
|
+
spec = [f"type :: {nm}_sf",
|
|
3441
|
+
f" integer(8), {attr} :: sf(:, :, :){init}",
|
|
3442
|
+
f"end type {nm}_sf"]
|
|
3443
|
+
dt = _dt_line(o)
|
|
3444
|
+
cont = [f" function {nm}_f(a, b, scale) result(r)", dt,
|
|
3445
|
+
" integer(8), intent(in) :: a, b",
|
|
3446
|
+
" integer(8), intent(in), optional :: scale",
|
|
3447
|
+
" integer(8) :: r", " if (present(scale)) then",
|
|
3448
|
+
" r = a + b * scale", " else", " r = a + b",
|
|
3449
|
+
" end if", f" end function {nm}_f"]
|
|
3450
|
+
return [Module(f"{nm}_m", spec, cont)]
|
|
3451
|
+
|
|
3452
|
+
def _bub_body(self):
|
|
3453
|
+
nb = self.p["nb"]
|
|
3454
|
+
m, n, p_ = self.p["ext"]
|
|
3455
|
+
nv = 2 * nb + 1
|
|
3456
|
+
o = self.o
|
|
3457
|
+
nm = self.name
|
|
3458
|
+
ind = " "
|
|
3459
|
+
lines = []
|
|
3460
|
+
for v in range(1, nv + 1):
|
|
3461
|
+
lines += [f"{ind}allocate(qp({v})%sf(0:{m - 1}, 0:{n - 1}, "
|
|
3462
|
+
f"0:{p_ - 1}))",
|
|
3463
|
+
f"{ind}do l = 0, {p_ - 1}", f"{ind} do k = 0, {n - 1}",
|
|
3464
|
+
f"{ind} do j = 0, {m - 1}",
|
|
3465
|
+
f"{ind} qp({v})%sf(j, k, l) = mod(j * 3 + k * 5 + "
|
|
3466
|
+
f"l * 7 + {v}, 37)",
|
|
3467
|
+
f"{ind} end do", f"{ind} end do", f"{ind}end do"]
|
|
3468
|
+
lines += [f"{ind}do q = 1, {nb}", f"{ind} rs(q) = q + 1",
|
|
3469
|
+
f"{ind} vs(q) = q + 1 + {nb}", f"{ind} w(q) = q",
|
|
3470
|
+
f"{ind}end do", f"{ind}cnt = 0", f"{ind}src = 0"]
|
|
3471
|
+
comps = [f"qp({v})%sf" for v in range(1, nv + 1)]
|
|
3472
|
+
if o.model == "omp":
|
|
3473
|
+
lines.append(f"{ind}{o.sent} target enter data map(to: qp)")
|
|
3474
|
+
lines += pack("target enter data", list_atoms("map", comps,
|
|
3475
|
+
"to"),
|
|
3476
|
+
ind, o.sent, o.width)
|
|
3477
|
+
chain = ("target teams distribute parallel do",)
|
|
3478
|
+
extra = []
|
|
3479
|
+
else:
|
|
3480
|
+
lines.append(f"{ind}{o.sent} enter data copyin(qp)")
|
|
3481
|
+
lines += pack("enter data", list_atoms("copyin", comps), ind,
|
|
3482
|
+
o.sent, o.width)
|
|
3483
|
+
chain = ("parallel loop gang vector",)
|
|
3484
|
+
extra = ["present(qp)"]
|
|
3485
|
+
op, cl, ii = region(o, chain, ind,
|
|
3486
|
+
data=[("rs", "to"), ("vs", "to"), ("w", "to"),
|
|
3487
|
+
("src", "tofrom"), ("cnt", "tofrom")],
|
|
3488
|
+
private=["j", "k", "l", "q", "rtmp", "vtmp",
|
|
3489
|
+
"r3", "nbub"], collapse=3, extra=extra)
|
|
3490
|
+
seq = [f"{o.sent} loop seq"] if o.model == "acc" else []
|
|
3491
|
+
lines += op + [f"{ii}do l = 0, {p_ - 1}", f"{ii} do k = 0, {n - 1}",
|
|
3492
|
+
f"{ii} do j = 0, {m - 1}"]
|
|
3493
|
+
jj = ii + " "
|
|
3494
|
+
lines += [jj + s for s in seq] + [
|
|
3495
|
+
f"{jj}do q = 1, {nb}",
|
|
3496
|
+
f"{jj} rtmp(q) = qp(rs(q))%sf(j, k, l)",
|
|
3497
|
+
f"{jj} vtmp(q) = qp(vs(q))%sf(j, k, l)", f"{jj}end do",
|
|
3498
|
+
f"{jj}r3 = 0"]
|
|
3499
|
+
lines += [jj + s for s in seq] + [
|
|
3500
|
+
f"{jj}do q = 1, {nb}", f"{jj} r3 = r3 + w(q) * rtmp(q)",
|
|
3501
|
+
f"{jj}end do",
|
|
3502
|
+
f"{jj}if (mod(j + k + l, 2) == 0) then",
|
|
3503
|
+
f"{jj} nbub = {nm}_f(r3, vtmp(1), scale=3_8)",
|
|
3504
|
+
f"{jj}else", f"{jj} nbub = {nm}_f(r3, vtmp(1))", f"{jj}end if",
|
|
3505
|
+
f"{jj}src(j, k, l) = nbub + qp(1)%sf(j, k, l)",
|
|
3506
|
+
f"{jj}if (mod(j + k + l, 5) == 0) then",
|
|
3507
|
+
f"{jj} {o.sent} atomic update", f"{jj} cnt = cnt + 1",
|
|
3508
|
+
f"{jj}end if",
|
|
3509
|
+
f"{ii} end do", f"{ii} end do", f"{ii}end do"] + cl
|
|
3510
|
+
if o.model == "omp":
|
|
3511
|
+
lines += pack("target exit data", list_atoms(
|
|
3512
|
+
"map", comps, "delete"), ind, o.sent, o.width)
|
|
3513
|
+
lines.append(f"{ind}{o.sent} target exit data map(delete: qp)")
|
|
3514
|
+
else:
|
|
3515
|
+
lines += pack("exit data", list_atoms("delete", comps), ind,
|
|
3516
|
+
o.sent, o.width)
|
|
3517
|
+
lines.append(f"{ind}{o.sent} exit data delete(qp)")
|
|
3518
|
+
lines += [f"{ind}call st_cksum(src, {m * n * p_}, cs)",
|
|
3519
|
+
f"{ind}cs = mod(cs * 31 + cnt, {P}_8)"]
|
|
3520
|
+
lines += [f"{ind}deallocate(qp({v})%sf)" for v in range(1, nv + 1)]
|
|
3521
|
+
return lines
|
|
3522
|
+
|
|
3523
|
+
def _bub_value(self):
|
|
3524
|
+
nb = self.p["nb"]
|
|
3525
|
+
m, n, p_ = self.p["ext"]
|
|
3526
|
+
|
|
3527
|
+
def sf(v, j, k, l):
|
|
3528
|
+
return (j * 3 + k * 5 + l * 7 + v) % 37
|
|
3529
|
+
src, cnt = [], 0
|
|
3530
|
+
for l in range(p_):
|
|
3531
|
+
for k in range(n):
|
|
3532
|
+
for j in range(m):
|
|
3533
|
+
rt = [sf(q + 1, j, k, l) for q in range(1, nb + 1)]
|
|
3534
|
+
vt = [sf(q + 1 + nb, j, k, l) for q in range(1, nb + 1)]
|
|
3535
|
+
r3 = sum(q * rt[q - 1] for q in range(1, nb + 1))
|
|
3536
|
+
nbub = r3 + vt[0] * (3 if (j + k + l) % 2 == 0 else 1)
|
|
3537
|
+
src.append(nbub + sf(1, j, k, l))
|
|
3538
|
+
if (j + k + l) % 5 == 0:
|
|
3539
|
+
cnt += 1
|
|
3540
|
+
return (cksum(src) * 31 + cnt) % P
|
|
3541
|
+
|
|
3542
|
+
# dispatch ------------------------------------------------------------------
|
|
3543
|
+
def modules(self):
|
|
3544
|
+
v = self.p["variant"]
|
|
3545
|
+
if v == "declared_alloc":
|
|
3546
|
+
return self._da_modules()
|
|
3547
|
+
if v == "mfc_cbc":
|
|
3548
|
+
return self._cbc_modules()
|
|
3549
|
+
if v == "mfc_bubbles":
|
|
3550
|
+
return self._bub_modules()
|
|
3551
|
+
return []
|
|
3552
|
+
|
|
3553
|
+
def uses(self):
|
|
3554
|
+
return [] if self.p["variant"] == "team_private" else \
|
|
3555
|
+
[f"{self.name}_m"]
|
|
3556
|
+
|
|
3557
|
+
def decls(self):
|
|
3558
|
+
v = self.p["variant"]
|
|
3559
|
+
if v == "team_private":
|
|
3560
|
+
n = self.p["w"] * self.p["nt"]
|
|
3561
|
+
return [f"integer(8) :: a({n}), b({n}), t(0:{self.p['w'] - 1})",
|
|
3562
|
+
"integer :: i, j, jj, jt, kt"]
|
|
3563
|
+
if v == "declared_alloc":
|
|
3564
|
+
return [f"integer(8) :: out({self.p['n']})", "integer :: i"]
|
|
3565
|
+
if v == "mfc_cbc":
|
|
3566
|
+
nf = self.p["nf"]
|
|
3567
|
+
return ["integer(8), allocatable :: q(:, :, :, :)",
|
|
3568
|
+
f"integer(8) :: flux({self.p['nk']}, {self.p['nr']})",
|
|
3569
|
+
"integer :: r, k, i, v, b, dir_idx",
|
|
3570
|
+
f"integer(8) :: alpha_rho({nf}), vel(3), adv({nf})",
|
|
3571
|
+
"integer(8) :: rho, gam, pres, c, accum"] + decl_lines(
|
|
3572
|
+
"integer(8)", self._cbc_privs(), self.o.width)
|
|
3573
|
+
nb = self.p["nb"]
|
|
3574
|
+
m, n, p_ = self.p["ext"]
|
|
3575
|
+
return [f"type({self.name}_sf) :: qp({2 * nb + 1})",
|
|
3576
|
+
f"integer :: rs({nb}), vs({nb})", f"integer(8) :: w({nb})",
|
|
3577
|
+
f"integer(8) :: src(0:{m - 1}, 0:{n - 1}, 0:{p_ - 1})",
|
|
3578
|
+
f"integer(8) :: rtmp({nb}), vtmp({nb}), r3, nbub, cnt",
|
|
3579
|
+
"integer :: j, k, l, q"]
|
|
3580
|
+
|
|
3581
|
+
def body(self):
|
|
3582
|
+
return {"team_private": self._tp_body,
|
|
3583
|
+
"declared_alloc": self._da_body,
|
|
3584
|
+
"mfc_cbc": self._cbc_body,
|
|
3585
|
+
"mfc_bubbles": self._bub_body}[self.p["variant"]]()
|
|
3586
|
+
|
|
3587
|
+
def value(self):
|
|
3588
|
+
return {"team_private": self._tp_value,
|
|
3589
|
+
"declared_alloc": self._da_value,
|
|
3590
|
+
"mfc_cbc": self._cbc_value,
|
|
3591
|
+
"mfc_bubbles": self._bub_value}[self.p["variant"]]()
|
|
3592
|
+
|
|
3593
|
+
def smaller(self):
|
|
3594
|
+
v = self.p["variant"]
|
|
3595
|
+
out = []
|
|
3596
|
+
if v == "team_private":
|
|
3597
|
+
if self.p["nloops"] > 2:
|
|
3598
|
+
out.append(self.clone(nloops=2))
|
|
3599
|
+
if self.p["simd"]:
|
|
3600
|
+
out.append(self.clone(simd=False))
|
|
3601
|
+
if self.p["col2"]:
|
|
3602
|
+
out.append(self.clone(col2=False))
|
|
3603
|
+
if self.p["w"] > 4:
|
|
3604
|
+
out.append(self.clone(w=4))
|
|
3605
|
+
elif v == "declared_alloc" and self.p["ncomp"] > 1:
|
|
3606
|
+
out.append(self.clone(ncomp=1))
|
|
3607
|
+
elif v == "mfc_cbc" and self.p["npriv"] > 1:
|
|
3608
|
+
out += [self.clone(npriv=m) for m in _halve(self.p["npriv"])]
|
|
3609
|
+
elif v == "mfc_bubbles" and self.p["nb"] > 1:
|
|
3610
|
+
out.append(self.clone(nb=1))
|
|
3611
|
+
return out
|
|
3612
|
+
|
|
3613
|
+
def features(self):
|
|
3614
|
+
return super().features() | {f"template:{self.p['variant']}"}
|
|
3615
|
+
|
|
3616
|
+
|
|
3617
|
+
# --- programs ------------------------------------------------------------------------------------
|
|
3618
|
+
|
|
3619
|
+
GEN = "stress-1"
|
|
3620
|
+
# The revision of each axis's programs. A
|
|
3621
|
+
# program record and a result row carry the revision they were made at
|
|
3622
|
+
# ("rev"); offload.engine.stress_report drops anything older than the current
|
|
3623
|
+
# revision (the generator changed the axis's text or its label since).
|
|
3624
|
+
# nest 2: deep nests wrapped and indented under 132 columns (ac364f0)
|
|
3625
|
+
# clauses 2: no linear / order(concurrent) (ac364f0); 3: lin private
|
|
3626
|
+
# random 2: the clauses change; 3: lin private
|
|
3627
|
+
# contlines (C) 2: one list item per continuation line (ac364f0)
|
|
3628
|
+
# tuimp 2: Fortran cross-module calls are cross-unit (an illegal
|
|
3629
|
+
# probe in every layout)
|
|
3630
|
+
# oo.polymap 2: an OpenMP 6.0 program
|
|
3631
|
+
# oo 3: the mixed axis has a polymap kernel, so its text changed too
|
|
3632
|
+
AXIS_REV = {"nest": 2, "clauses": 3, "random": 3, "contlines-c": 2,
|
|
3633
|
+
"tuimp": 2, "oo.polymap": 2, "oo": 3}
|
|
3634
|
+
|
|
3635
|
+
|
|
3636
|
+
def axis_rev(axis: str, lang: str = "f90") -> int:
|
|
3637
|
+
if lang == "c":
|
|
3638
|
+
return AXIS_REV.get(f"{axis}-c", 1)
|
|
3639
|
+
return AXIS_REV.get(axis, AXIS_REV.get(axis.split(".")[0], 1)
|
|
3640
|
+
if axis.split(".")[0] in ("nest", "clauses",
|
|
3641
|
+
"random", "tuimp")
|
|
3642
|
+
else 1)
|
|
3643
|
+
LAYOUTS = ("single", "per_unit", "partition")
|
|
3644
|
+
|
|
3645
|
+
UTIL = f"""module st_util
|
|
3646
|
+
implicit none
|
|
3647
|
+
integer(8), parameter :: st_p = {P}_8
|
|
3648
|
+
type :: st_pair
|
|
3649
|
+
integer(8) :: u, v
|
|
3650
|
+
end type st_pair
|
|
3651
|
+
contains
|
|
3652
|
+
subroutine st_cksum(a, n, cs)
|
|
3653
|
+
integer, intent(in) :: n
|
|
3654
|
+
integer(8), intent(in) :: a(n)
|
|
3655
|
+
integer(8), intent(out) :: cs
|
|
3656
|
+
integer :: i
|
|
3657
|
+
cs = 0
|
|
3658
|
+
do i = 1, n
|
|
3659
|
+
cs = mod(cs + mod(a(i), st_p) * (mod(i, 7) + 1), st_p)
|
|
3660
|
+
end do
|
|
3661
|
+
end subroutine st_cksum
|
|
3662
|
+
end module st_util
|
|
3663
|
+
"""
|
|
3664
|
+
|
|
3665
|
+
|
|
3666
|
+
def module_text(m: Module) -> str:
|
|
3667
|
+
uses = []
|
|
3668
|
+
for u in ["st_util"] + list(m.uses):
|
|
3669
|
+
if u not in uses:
|
|
3670
|
+
uses.append(u)
|
|
3671
|
+
lines = [f"module {m.name}"] + [f" use {u}" for u in uses] + \
|
|
3672
|
+
[" implicit none"]
|
|
3673
|
+
lines += [" " + s if s and not s.startswith(" ") else s for s in m.spec]
|
|
3674
|
+
if m.contains:
|
|
3675
|
+
lines.append("contains")
|
|
3676
|
+
lines += m.contains
|
|
3677
|
+
lines.append(f"end module {m.name}")
|
|
3678
|
+
return "\n".join(lines) + "\n"
|
|
3679
|
+
|
|
3680
|
+
|
|
3681
|
+
@dataclass
|
|
3682
|
+
class StressProgram:
|
|
3683
|
+
id: str
|
|
3684
|
+
axis: str
|
|
3685
|
+
size: int
|
|
3686
|
+
seed: int
|
|
3687
|
+
model: str
|
|
3688
|
+
layout: str
|
|
3689
|
+
kernels: list
|
|
3690
|
+
files: list # [(name, text)] in compile order
|
|
3691
|
+
expected: int
|
|
3692
|
+
per_kernel: dict
|
|
3693
|
+
legality: str = "legal"
|
|
3694
|
+
cite: str = ""
|
|
3695
|
+
features: set = field(default_factory=set)
|
|
3696
|
+
alloc_bytes: int = 0
|
|
3697
|
+
lang: str = "f90"
|
|
3698
|
+
gen: str = GEN
|
|
3699
|
+
limits: dict = field(default_factory=dict)
|
|
3700
|
+
rev: int = 1
|
|
3701
|
+
|
|
3702
|
+
@property
|
|
3703
|
+
def source(self) -> str:
|
|
3704
|
+
if len(self.files) == 1:
|
|
3705
|
+
return self.files[0][1]
|
|
3706
|
+
return "".join(f"{FILE_MARK}{n}\n{t}" for n, t in self.files)
|
|
3707
|
+
|
|
3708
|
+
@property
|
|
3709
|
+
def lines(self) -> int:
|
|
3710
|
+
return sum(t.count("\n") for _, t in self.files)
|
|
3711
|
+
|
|
3712
|
+
def meta(self) -> dict:
|
|
3713
|
+
return {"id": self.id, "gen": self.gen, "rev": self.rev,
|
|
3714
|
+
"axis": self.axis,
|
|
3715
|
+
"size": self.size, "seed": self.seed, "model": self.model,
|
|
3716
|
+
"lang": self.lang, "layout": self.layout,
|
|
3717
|
+
"legality": self.legality, "cite": self.cite,
|
|
3718
|
+
"expected": self.expected, "lines": self.lines,
|
|
3719
|
+
"files": len(self.files), "kernels": [
|
|
3720
|
+
k.describe() for k in self.kernels],
|
|
3721
|
+
"per_kernel": self.per_kernel,
|
|
3722
|
+
"features": sorted(self.features),
|
|
3723
|
+
"alloc_bytes": self.alloc_bytes, "limits": self.limits}
|
|
3724
|
+
|
|
3725
|
+
|
|
3726
|
+
def main_text(kernels: list, o: Opts, kmods: list[str]) -> str:
|
|
3727
|
+
lines = ["program stress_main", " use st_util"]
|
|
3728
|
+
lines += [f" use {m}" for m in kmods]
|
|
3729
|
+
lines.append(" use omp_lib" if o.model == "omp" else " use openacc")
|
|
3730
|
+
lines += [" implicit none", " integer(8) :: cs, total",
|
|
3731
|
+
" integer :: onhost", " total = 0"]
|
|
3732
|
+
for k in kernels:
|
|
3733
|
+
lines += [f" call {k.name}(cs)",
|
|
3734
|
+
f" print '(a,i0)', 'K {k.name} ', cs",
|
|
3735
|
+
" total = mod(total + cs, st_p)"]
|
|
3736
|
+
lines.append(" onhost = 1")
|
|
3737
|
+
if o.model == "omp":
|
|
3738
|
+
lines += [" !$omp target map(tofrom: onhost)",
|
|
3739
|
+
" if (.not. omp_is_initial_device()) onhost = 0",
|
|
3740
|
+
" !$omp end target"]
|
|
3741
|
+
else:
|
|
3742
|
+
lines += [" !$acc serial copy(onhost)",
|
|
3743
|
+
" if (acc_on_device(acc_device_not_host)) onhost = 0",
|
|
3744
|
+
" !$acc end serial"]
|
|
3745
|
+
lines += [" print '(a,i0,a,i0)', 'RESULT checksum=', total, "
|
|
3746
|
+
"' ran_on_host=', onhost", "end program stress_main"]
|
|
3747
|
+
return "\n".join(lines) + "\n"
|
|
3748
|
+
|
|
3749
|
+
|
|
3750
|
+
_ID = re.compile(r"[A-Za-z][A-Za-z0-9_]*")
|
|
3751
|
+
|
|
3752
|
+
|
|
3753
|
+
def check_limits(files: list) -> dict:
|
|
3754
|
+
"""Base-language limits of the rendered text (Fortran files): the
|
|
3755
|
+
longest line, the most continuation lines of one statement or
|
|
3756
|
+
directive, the longest name; with ``violations`` (keys of CITES)."""
|
|
3757
|
+
longest = cont_max = name_max = 0
|
|
3758
|
+
for name, text in files:
|
|
3759
|
+
if not name.endswith(".f90"):
|
|
3760
|
+
continue
|
|
3761
|
+
run = 0
|
|
3762
|
+
for ln in text.splitlines():
|
|
3763
|
+
longest = max(longest, len(ln))
|
|
3764
|
+
body = ln.split("!", 1)[0] if not ln.lstrip().startswith(
|
|
3765
|
+
"!$") else ln.lstrip()[5:]
|
|
3766
|
+
if ln.lstrip().startswith("!") and not ln.lstrip().startswith(
|
|
3767
|
+
"!$"):
|
|
3768
|
+
continue
|
|
3769
|
+
if ln.rstrip().endswith("&"):
|
|
3770
|
+
run += 1
|
|
3771
|
+
cont_max = max(cont_max, run)
|
|
3772
|
+
else:
|
|
3773
|
+
run = 0
|
|
3774
|
+
for t in _ID.findall(re.sub(r"'[^']*'|\"[^\"]*\"", "", body)):
|
|
3775
|
+
name_max = max(name_max, len(t))
|
|
3776
|
+
v = []
|
|
3777
|
+
if longest > LINE_MAX:
|
|
3778
|
+
v.append("line")
|
|
3779
|
+
if cont_max > CONT_MAX:
|
|
3780
|
+
v.append("cont")
|
|
3781
|
+
if name_max > NAME_MAX:
|
|
3782
|
+
v.append("name")
|
|
3783
|
+
return {"max_line": longest, "max_continuations": cont_max,
|
|
3784
|
+
"max_name": name_max, "violations": v}
|
|
3785
|
+
|
|
3786
|
+
|
|
3787
|
+
def assemble(axis: str, size: int, seed: int, kernels: list, o: Opts,
|
|
3788
|
+
layout: str = "single", rng: random.Random | None = None
|
|
3789
|
+
) -> StressProgram:
|
|
3790
|
+
"""Render `kernels` into files per `layout`; compute the value, the
|
|
3791
|
+
limits and the legality label."""
|
|
3792
|
+
rng = rng or random.Random(f"layout:{seed}")
|
|
3793
|
+
units: list[tuple[str, str, str]] = [("st_util", "mod", UTIL)]
|
|
3794
|
+
extra_after: dict[str, list] = {}
|
|
3795
|
+
kmods = []
|
|
3796
|
+
for k in kernels:
|
|
3797
|
+
for m in k.modules():
|
|
3798
|
+
units.append((m.name, "mod", module_text(m)))
|
|
3799
|
+
if hasattr(k, "extra_files"):
|
|
3800
|
+
for fname, text in k.extra_files():
|
|
3801
|
+
units.append((fname, "file", text))
|
|
3802
|
+
# the kernel subroutines: one module per kernel (per_unit / partition)
|
|
3803
|
+
# or one module for all (single)
|
|
3804
|
+
if layout == "single":
|
|
3805
|
+
body = ["module st_kern", " use st_util", " implicit none",
|
|
3806
|
+
"contains"]
|
|
3807
|
+
for k in kernels:
|
|
3808
|
+
body += k.routine()
|
|
3809
|
+
body.append("end module st_kern")
|
|
3810
|
+
units.append(("st_kern", "mod", "\n".join(body) + "\n"))
|
|
3811
|
+
kmods = ["st_kern"]
|
|
3812
|
+
else:
|
|
3813
|
+
for k in kernels:
|
|
3814
|
+
mname = f"st_k_{k.name}"
|
|
3815
|
+
body = [f"module {mname}", " use st_util", " implicit none",
|
|
3816
|
+
"contains"] + k.routine() + [f"end module {mname}"]
|
|
3817
|
+
units.append((mname, "mod", "\n".join(body) + "\n"))
|
|
3818
|
+
kmods.append(mname)
|
|
3819
|
+
main = main_text(kernels, o, kmods)
|
|
3820
|
+
omp_level = "6.0" if any(isinstance(k, OOKernel) and
|
|
3821
|
+
k.p.get("variant") == "polymap"
|
|
3822
|
+
for k in kernels) else "5.2 in 5.0 spellings"
|
|
3823
|
+
head = [f"! stress: axis={axis} size={size} seed={seed} model={o.model}"
|
|
3824
|
+
f" layout={layout}",
|
|
3825
|
+
f"! generator: {GEN} rev {axis_rev(axis)}",
|
|
3826
|
+
f"! language: Fortran 2018 free form; OpenMP {omp_level}"
|
|
3827
|
+
if o.model == "omp" else
|
|
3828
|
+
"! language: Fortran 2018 free form; OpenACC 3.4"]
|
|
3829
|
+
for k in kernels:
|
|
3830
|
+
head.append(("! kernel " + k.describe())[:120])
|
|
3831
|
+
header = "\n".join(head) + "\n"
|
|
3832
|
+
# files
|
|
3833
|
+
fort = [u for u in units if u[1] == "mod"]
|
|
3834
|
+
others = [u for u in units if u[1] == "file"]
|
|
3835
|
+
files: list[tuple[str, str]] = []
|
|
3836
|
+
if layout == "single":
|
|
3837
|
+
text = header + "".join(t for _, _, t in fort) + main
|
|
3838
|
+
files.append(("stress.f90", text))
|
|
3839
|
+
# a submodule must follow its ancestor module: its own file after
|
|
3840
|
+
files += [(n, t) for n, _, t in others]
|
|
3841
|
+
elif layout == "per_unit":
|
|
3842
|
+
files.append(("st_util.f90", header + UTIL))
|
|
3843
|
+
for n, kind, t in fort[1:]:
|
|
3844
|
+
files.append((f"{n}.f90", t))
|
|
3845
|
+
files += [(n, t) for n, _, t in others]
|
|
3846
|
+
files.append(("main.f90", main))
|
|
3847
|
+
else:
|
|
3848
|
+
# random partition into contiguous groups (module order is kept)
|
|
3849
|
+
nf = max(2, min(len(fort), rng.randint(2, max(2, len(fort) // 2))))
|
|
3850
|
+
cuts = sorted(rng.sample(range(1, len(fort)), min(nf - 1,
|
|
3851
|
+
len(fort) - 1)))
|
|
3852
|
+
groups, prev = [], 0
|
|
3853
|
+
for c in cuts + [len(fort)]:
|
|
3854
|
+
groups.append(fort[prev:c])
|
|
3855
|
+
prev = c
|
|
3856
|
+
for g_i, g in enumerate(groups):
|
|
3857
|
+
text = (header if g_i == 0 else "") + "".join(t for _, _, t in g)
|
|
3858
|
+
files.append((f"part{g_i:03d}.f90", text))
|
|
3859
|
+
files += [(n, t) for n, _, t in others]
|
|
3860
|
+
files.append(("main.f90", main))
|
|
3861
|
+
per = {k.name: k.value() for k in kernels}
|
|
3862
|
+
expected = sum(per.values()) % P
|
|
3863
|
+
feats = set()
|
|
3864
|
+
for k in kernels:
|
|
3865
|
+
feats |= k.features()
|
|
3866
|
+
lim = check_limits(files)
|
|
3867
|
+
legality, cite = "legal", ""
|
|
3868
|
+
for k in kernels:
|
|
3869
|
+
if k.legality == "unspecified" and legality == "legal":
|
|
3870
|
+
legality, cite = "unspecified", k.cite
|
|
3871
|
+
# implicit device procedures across compilation units (OpenMP 5.2
|
|
3872
|
+
# §13.8 p.284, §5.8.4 p.158). For Fortran a compilation unit is a
|
|
3873
|
+
# program unit (5.2 §1.2.2 p.3; OpenACC 3.4 §2.15.1 p.91: "program unit
|
|
3874
|
+
# being compiled"), so a chain of procedures in other modules is
|
|
3875
|
+
# cross-unit even in one file (F7): an illegal
|
|
3876
|
+
# probe in every layout
|
|
3877
|
+
for k in kernels:
|
|
3878
|
+
if isinstance(k, ChainTUKernel) and k.p["variant"] == "implicit":
|
|
3879
|
+
legality, cite = "illegal_probe", CITES["xtu"]
|
|
3880
|
+
if lim["violations"]:
|
|
3881
|
+
legality = "illegal_probe"
|
|
3882
|
+
cite = "; ".join(CITES[v] for v in lim["violations"])
|
|
3883
|
+
alloc = sum(k.bytes() for k in kernels if hasattr(k, "bytes"))
|
|
3884
|
+
pid = f"{axis}-{o.model}-{size}-{seed}" + ("" if layout == "single"
|
|
3885
|
+
else f"-{layout}")
|
|
3886
|
+
feats |= {f"axis:{axis}", f"layout:{layout}"}
|
|
3887
|
+
return StressProgram(pid, axis, size, seed, o.model, layout, kernels,
|
|
3888
|
+
files, expected, per, legality, cite, feats, alloc,
|
|
3889
|
+
limits=lim, rev=axis_rev(axis))
|
|
3890
|
+
|
|
3891
|
+
|
|
3892
|
+
# --- axes ----------------------------------------------------------------------------------------
|
|
3893
|
+
|
|
3894
|
+
def _k(i: int) -> str:
|
|
3895
|
+
return f"k{i:04d}"
|
|
3896
|
+
|
|
3897
|
+
|
|
3898
|
+
def kernel_variant(k: Kernel) -> str | None:
|
|
3899
|
+
"""The variant (route, template, ...) a kernel instantiates."""
|
|
3900
|
+
if "routes" in k.p and len(k.p["routes"]) == 1:
|
|
3901
|
+
return k.p["routes"][0]
|
|
3902
|
+
return k.p.get("variant")
|
|
3903
|
+
|
|
3904
|
+
|
|
3905
|
+
def _kernels_for(axis: str, size: int, rng: random.Random, o: Opts) -> list:
|
|
3906
|
+
"""The kernels of one axis at one size; ``<axis>.<variant>`` keeps the
|
|
3907
|
+
kernels of one variant (a scalar route, an OO feature, a template, a
|
|
3908
|
+
translation-unit variant, ...), so a rejection of one variant does not
|
|
3909
|
+
hide the others."""
|
|
3910
|
+
if "." in axis:
|
|
3911
|
+
base, var = axis.split(".", 1)
|
|
3912
|
+
ks = [k for k in _kernels_for(base, size, rng, o)
|
|
3913
|
+
if kernel_variant(k) == var]
|
|
3914
|
+
if not ks:
|
|
3915
|
+
raise ValueError(f"axis {base} has no variant {var}")
|
|
3916
|
+
for j, k in enumerate(ks, 1):
|
|
3917
|
+
k.name = _k(j)
|
|
3918
|
+
return ks
|
|
3919
|
+
ks: list[Kernel] = []
|
|
3920
|
+
if o.model == "acc" and axis in ACC_EXCLUDED:
|
|
3921
|
+
raise ValueError(f"the {axis} axis is OpenMP only")
|
|
3922
|
+
|
|
3923
|
+
def add(cls, **p):
|
|
3924
|
+
ks.append(cls(_k(len(ks) + 1), o, random.Random(rng.random()), **p))
|
|
3925
|
+
if axis == "kernels":
|
|
3926
|
+
for _ in range(size):
|
|
3927
|
+
r = rng.random()
|
|
3928
|
+
if r < 0.8:
|
|
3929
|
+
add(LoopKernel)
|
|
3930
|
+
elif r < 0.9:
|
|
3931
|
+
add(PrivateKernel, nitems=4)
|
|
3932
|
+
else:
|
|
3933
|
+
add(CallsKernel, depth=2, recursive=False, n=64)
|
|
3934
|
+
elif axis == "nest":
|
|
3935
|
+
add(NestKernel, depth=size, collapse=size)
|
|
3936
|
+
if size >= 3 and o.model == "omp":
|
|
3937
|
+
add(NestKernel, depth=size, split=True)
|
|
3938
|
+
add(NestKernel, depth=size, collapse=1)
|
|
3939
|
+
elif axis == "calls":
|
|
3940
|
+
add(CallsKernel, depth=size, recursive=False)
|
|
3941
|
+
add(CallsKernel, depth=size, recursive=True)
|
|
3942
|
+
elif axis in LIST_AXES:
|
|
3943
|
+
if axis == "lastprivate" and o.model == "acc":
|
|
3944
|
+
raise ValueError("OpenACC has no lastprivate")
|
|
3945
|
+
add(LIST_AXES[axis], nitems=size)
|
|
3946
|
+
elif axis == "clauses":
|
|
3947
|
+
if o.model == "acc":
|
|
3948
|
+
raise ValueError("the clauses axis is OpenMP")
|
|
3949
|
+
add(ClausesKernel, nclauses=size)
|
|
3950
|
+
elif axis == "contlines":
|
|
3951
|
+
add(ContKernel, nitems=size, n=8)
|
|
3952
|
+
elif axis == "names":
|
|
3953
|
+
add(NamesKernel, length=size, count=4)
|
|
3954
|
+
elif axis == "locals":
|
|
3955
|
+
add(LocalsKernel, nlocals=size)
|
|
3956
|
+
elif axis == "args":
|
|
3957
|
+
add(ArgsKernel, nargs=size)
|
|
3958
|
+
elif axis == "useonly":
|
|
3959
|
+
add(UseOnlyKernel, nitems=size)
|
|
3960
|
+
elif axis == "capture":
|
|
3961
|
+
add(CaptureKernel, nitems=size)
|
|
3962
|
+
elif axis == "dtnest":
|
|
3963
|
+
add(DTNestKernel, depth=size, mode="enter", ptr=False)
|
|
3964
|
+
add(DTNestKernel, depth=size, mode="region", ptr=False)
|
|
3965
|
+
add(DTNestKernel, depth=size, mode="enter", ptr=True)
|
|
3966
|
+
elif axis == "oo":
|
|
3967
|
+
for v in OO_LEGAL:
|
|
3968
|
+
add(OOKernel, variant=v, depth=size)
|
|
3969
|
+
add(OOKernel, variant="polymap", depth=size)
|
|
3970
|
+
add(OOKernel, variant="pdt", depth=size)
|
|
3971
|
+
elif axis == "tu":
|
|
3972
|
+
for v in ("plain", "submodule") + (
|
|
3973
|
+
("bindc",) if o.model == "omp" else ()):
|
|
3974
|
+
add(ChainTUKernel, depth=size, variant=v)
|
|
3975
|
+
elif axis == "tuimp":
|
|
3976
|
+
add(ChainTUKernel, depth=size, variant="implicit")
|
|
3977
|
+
elif axis == "scalars":
|
|
3978
|
+
routes = OMP_ROUTES if o.model == "omp" else ACC_ROUTES
|
|
3979
|
+
for r in routes:
|
|
3980
|
+
add(ScalarsKernel, nscal=size, routes=[r])
|
|
3981
|
+
elif axis == "mixed":
|
|
3982
|
+
add(MixedKernel, nred=size, natom=max(1, size // 2),
|
|
3983
|
+
ncrit=max(1, min(size, 64) // 2) if o.model == "omp" else 0)
|
|
3984
|
+
elif axis == "exprs":
|
|
3985
|
+
for v in ("expr", "select", "spec"):
|
|
3986
|
+
add(ExprsKernel, variant=v, size=size)
|
|
3987
|
+
elif axis == "async":
|
|
3988
|
+
add(AsyncKernel, ntasks=size)
|
|
3989
|
+
elif axis == "runtime":
|
|
3990
|
+
for v in ("iters", "teams", "alloc"):
|
|
3991
|
+
sz = {"iters": size, "teams": max(1, size // 256),
|
|
3992
|
+
"alloc": size}[v]
|
|
3993
|
+
add(RuntimeKernel, variant=v, size=sz)
|
|
3994
|
+
elif axis == "template":
|
|
3995
|
+
add(TemplateKernel, variant="team_private", nloops=max(2, min(size,
|
|
3996
|
+
16)))
|
|
3997
|
+
add(TemplateKernel, variant="declared_alloc", ncomp=max(1, min(
|
|
3998
|
+
size, 64)))
|
|
3999
|
+
add(TemplateKernel, variant="mfc_cbc", npriv=size)
|
|
4000
|
+
add(TemplateKernel, variant="mfc_bubbles", nb=max(1, min(size, 32)))
|
|
4001
|
+
elif axis == "random":
|
|
4002
|
+
# every axis together: `size` kernels drawn from the axes at
|
|
4003
|
+
# moderate sizes
|
|
4004
|
+
pool = [a for a in AXES if a not in ("random", "runtime", "names",
|
|
4005
|
+
"contlines", "tuimp",
|
|
4006
|
+
"oo", "scalars", "udr")]
|
|
4007
|
+
if o.model == "acc":
|
|
4008
|
+
pool = [a for a in pool if a not in ACC_EXCLUDED]
|
|
4009
|
+
for _ in range(size):
|
|
4010
|
+
a = rng.choice(pool)
|
|
4011
|
+
sub = _kernels_for(a, rng.choice(SMALL_SIZES.get(a, (4, 8, 16))),
|
|
4012
|
+
random.Random(rng.random()), o)
|
|
4013
|
+
for k in sub[:1]:
|
|
4014
|
+
k.name = _k(len(ks) + 1)
|
|
4015
|
+
ks.append(k)
|
|
4016
|
+
else:
|
|
4017
|
+
raise ValueError(f"unknown axis {axis}")
|
|
4018
|
+
return ks
|
|
4019
|
+
|
|
4020
|
+
|
|
4021
|
+
LIST_AXES = {"private": PrivateKernel, "firstprivate": FirstprivateKernel,
|
|
4022
|
+
"udr": UDRKernel,
|
|
4023
|
+
"lastprivate": LastprivateKernel, "shared": SharedKernel,
|
|
4024
|
+
"map": MapKernel, "reduction": ReductionKernel,
|
|
4025
|
+
"depend": DependKernel, "declare": DeclareKernel,
|
|
4026
|
+
"sections": SectionsKernel}
|
|
4027
|
+
AXES = ("kernels", "nest", "calls", *LIST_AXES, "clauses", "contlines",
|
|
4028
|
+
"names", "locals", "args", "useonly", "capture", "dtnest", "oo",
|
|
4029
|
+
"tu", "tuimp", "scalars", "mixed", "exprs", "async", "runtime", "template",
|
|
4030
|
+
"random")
|
|
4031
|
+
ACC_EXCLUDED = ("lastprivate", "clauses", "udr")
|
|
4032
|
+
SMALL_SIZES = {"kernels": (2, 4), "nest": (3, 4, 5), "calls": (3, 5),
|
|
4033
|
+
"dtnest": (2, 3), "oo": (2,), "tu": (2, 3), "scalars": (1, 2),
|
|
4034
|
+
"template": (4, 8), "names": (40, 63), "exprs": (16, 64),
|
|
4035
|
+
"async": (4, 8), "mixed": (2, 4), "clauses": (8, 16, 28)}
|
|
4036
|
+
# the size sweep of each axis (1, 8, 64, 256, 1024 ... and the
|
|
4037
|
+
# real maximum x2 to x10, set from catalog/fuzz_profile.json by
|
|
4038
|
+
# offload.engine.fuzz_profile.sweeps; these are the defaults)
|
|
4039
|
+
SWEEPS = {
|
|
4040
|
+
"kernels": (1, 8, 64, 256, 512),
|
|
4041
|
+
"nest": (1, 2, 3, 4, 5, 6, 7, 8, 10, 12),
|
|
4042
|
+
"calls": (1, 2, 5, 10, 20, 50),
|
|
4043
|
+
"private": (1, 8, 64, 159, 256, 512, 1024, 2048),
|
|
4044
|
+
"firstprivate": (1, 8, 64, 256, 1024),
|
|
4045
|
+
"lastprivate": (1, 8, 64, 256, 1024),
|
|
4046
|
+
"shared": (1, 8, 64, 256, 1024),
|
|
4047
|
+
"map": (1, 8, 64, 256, 1024),
|
|
4048
|
+
"reduction": (1, 8, 64, 256, 1024),
|
|
4049
|
+
"udr": (1, 8, 64, 256, 1024),
|
|
4050
|
+
"depend": (1, 8, 64, 256, 1024),
|
|
4051
|
+
"declare": (1, 8, 64, 113, 256, 1024),
|
|
4052
|
+
"sections": (1, 8, 64, 256, 1024),
|
|
4053
|
+
"clauses": (1, 8, 16, 28, 64, 256),
|
|
4054
|
+
"contlines": (1, 8, 64, 200, 255, 256, 300),
|
|
4055
|
+
"names": (31, 63, 64, 128),
|
|
4056
|
+
"locals": (1, 8, 64, 190, 512, 1024, 2048),
|
|
4057
|
+
"args": (1, 8, 25, 64, 128, 250),
|
|
4058
|
+
"useonly": (1, 16, 64, 160, 1024),
|
|
4059
|
+
"capture": (1, 8, 20, 64, 200, 1024),
|
|
4060
|
+
"dtnest": (1, 2, 3, 4, 6, 8, 12),
|
|
4061
|
+
"oo": (1, 3, 6),
|
|
4062
|
+
"tu": (2, 3, 5, 8, 16, 32),
|
|
4063
|
+
"tuimp": (2, 3, 5, 8),
|
|
4064
|
+
"scalars": (1, 4, 20, 64, 200),
|
|
4065
|
+
"mixed": (1, 8, 64, 256),
|
|
4066
|
+
"exprs": (8, 64, 256, 1024, 2048),
|
|
4067
|
+
"async": (1, 8, 64, 256),
|
|
4068
|
+
"runtime": (1 << 20, 1 << 24, 1 << 28, 1 << 30),
|
|
4069
|
+
"template": (8, 40, 159, 400),
|
|
4070
|
+
"random": (8, 32, 128),
|
|
4071
|
+
}
|
|
4072
|
+
|
|
4073
|
+
|
|
4074
|
+
def variants_of(axis: str, model: str = "omp") -> tuple:
|
|
4075
|
+
"""The variants ``<axis>.<variant>`` of an axis (empty: no split)."""
|
|
4076
|
+
return {
|
|
4077
|
+
"oo": OO_VARIANTS,
|
|
4078
|
+
"scalars": tuple(OMP_ROUTES if model == "omp" else ACC_ROUTES),
|
|
4079
|
+
"tu": ("plain", "submodule") + (("bindc",) if model == "omp"
|
|
4080
|
+
else ()),
|
|
4081
|
+
"template": TEMPLATES,
|
|
4082
|
+
"exprs": ("expr", "select", "spec"),
|
|
4083
|
+
"runtime": ("iters", "teams", "alloc"),
|
|
4084
|
+
}.get(axis, ())
|
|
4085
|
+
|
|
4086
|
+
|
|
4087
|
+
def axis_names(model: str = "omp", split: bool = True) -> list[str]:
|
|
4088
|
+
"""Every axis of a model, split into its variants where it has
|
|
4089
|
+
them."""
|
|
4090
|
+
out = []
|
|
4091
|
+
for a in AXES:
|
|
4092
|
+
if model == "acc" and a in ACC_EXCLUDED:
|
|
4093
|
+
continue
|
|
4094
|
+
vs = variants_of(a, model) if split else ()
|
|
4095
|
+
out += [f"{a}.{v}" for v in vs] if vs else [a]
|
|
4096
|
+
return out
|
|
4097
|
+
|
|
4098
|
+
|
|
4099
|
+
def build(axis: str, size: int, seed: int = 0, model: str = "omp",
|
|
4100
|
+
layout: str = "single", width: int = WIDTH) -> StressProgram:
|
|
4101
|
+
"""The stress program of one axis at one size (deterministic in
|
|
4102
|
+
axis, size, seed, model, layout)."""
|
|
4103
|
+
o = Opts(model=model, width=width)
|
|
4104
|
+
rng = random.Random(f"{GEN}:{axis}:{size}:{seed}:{model}")
|
|
4105
|
+
for attempt in range(20):
|
|
4106
|
+
ks = _kernels_for(axis, size, rng, o)
|
|
4107
|
+
try:
|
|
4108
|
+
return assemble(axis, size, seed, ks, o, layout,
|
|
4109
|
+
random.Random(f"layout:{seed}:{attempt}"))
|
|
4110
|
+
except Overflow:
|
|
4111
|
+
continue
|
|
4112
|
+
raise RuntimeError(f"{axis} {size} {seed}: model overflow 20 times")
|
|
4113
|
+
|
|
4114
|
+
|
|
4115
|
+
def rebuild(prog_meta: dict, kernels: list) -> StressProgram:
|
|
4116
|
+
"""A program of `kernels` (a subset or shrunk variants) with the
|
|
4117
|
+
original's axis, seed, model and layout (offload.engine.stress_min)."""
|
|
4118
|
+
o = Opts(model=prog_meta["model"])
|
|
4119
|
+
for j, k in enumerate(kernels, 1):
|
|
4120
|
+
k.o = o
|
|
4121
|
+
return assemble(prog_meta["axis"], prog_meta["size"], prog_meta["seed"],
|
|
4122
|
+
kernels, o, prog_meta["layout"])
|