Repository navigation
[Draft, for CI] FaCe - #2448
Draft
ThrudPrimrose wants to merge 946 commits into
Draft
[Draft, for CI] FaCe#2448ThrudPrimrose wants to merge 946 commits into
ThrudPrimrose wants to merge 946 commits into
Conversation
- ``Range.size``: a dimension that is a single index of an integer, a symbol or a sum of those (with unit step and tile size) has size one, which ``ceiling((i + 1 - i) / 1)`` always evaluates to; it is returned without building and simplifying the expression. - ``Range.free_symbols``: symbols and numbers are handled directly instead of through ``symlist``, and the result is updated in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scalar-ness of an input memlet (which computes its number of elements) is only needed to infer the type of a connector that has none, so it is no longer computed for the other connectors. Code generation infers connector types three times, and the later passes find almost all connectors typed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
``symbols_defined_at_state`` walks from the SDFG down to the state and, at each level, adds the symbols the control flow region defines (for a loop, inferring the type of its variable) and those of the inter-state edges leading to the next block. For states nested in many regions, this redid the same work for every state. Both parts only depend on the blocks around them, so the resolver now records these updates per region (and per region and block) and replays them, in the same order, for the other states. The resulting symbols and their order are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
``cfg_id`` caches the position of a CFG in the CFG list, but the first query of each CFG searched the list linearly, which is quadratic when all regions of a large SDFG are queried after ``reset_cfg_list`` (e.g., by the reachability analyses). The reset now records the position of each CFG (its first occurrence) while propagating the new list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
to_json time is dominated by the traversal (json.dumps is <0.5s), mostly by printing symbolic expressions and property bookkeeping. Output is unchanged (identical JSON on all tested SDFGs). On a test SDFG with ~4k states and ~8.5k control flow regions, to_json takes 10.8s instead of 49.6s; on a smaller SDFG with large states, 40s instead of 89s. - serialize_symbolic: print integers and lone symbols directly, and cache the serialization of other expressions keyed by the expression and the dtypes its DaCe symbols are printed with (SymPy equality ignores symbol dtypes). Cache the serializer keyword arguments of symbols. - serialization_symbol_dtypes: push a lazily filtered view of the authoritative dtypes instead of filtering a copy of all SDFG symbols for every node and edge; edges look names up in both endpoints' scopes through a ChainMap instead of merging copies. - CodeProperty / CodeBlock serialization: cache the parse/unparse normalization of code strings, and compare with None without unparsing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Operands are read through broadcast_together (unidirectional), SPREAD is the NumPy rule with an inserted extent-1 axis, and a one-element operand is a scalar of any rank. Both nodes validate shapes before expansion. Tests are parametrized and cover scalars, slices with offsets, symbolic extents, strides and type conversion; numpy.broadcast_to is listed in the NumPy support doc.
Cases that reused one SDFG name in a process loaded the library a previous case had built, which gave wrong results and crashes.
networkx 3.6 no longer includes the start node (mapped to itself) in the result of immediate_dominators. DaCe indexes the dominator of every block and walks the dominator tree until a block is its own dominator, so code generation failed with a KeyError (block_parent_tree, called from determine_allocation_lifetime) and loop detection, control flow raising and the symbol/scalar analyses broke the same way. Add sdutil.immediate_dominators, which always maps the start node to itself, and use it at every dominator and postdominator call site. Drop the networkx<=3.5 pin from pyproject.toml and lock networkx 3.4.2 on Python 3.10, 3.6.1 on 3.11 and 3.7 on 3.12 and later, so CI exercises both the old and the new behaviour.
An integral base truncates 1 / a**|b| toward zero, which is non-zero only for a base of +-1 and 0 for a zero base; a floating-point or complex base gets the exact reciprocal; the typed pow and the global ipow share one helper for the integral case. ipow in sympy refuses any negative constant exponent, integer-valued or not. Tests compile the runtime under UBSan and compare with NumPy, and cover the unknown-sign symbolic exponent.
A register array now carries stack_vla (Auto, Stack, Heap). The ResolveStackAllocation pass, run before code generation, resolves Auto: constant sizes below 2048 elements and max_stack_array_size bytes go on the stack, symbolic sizes on the heap. An explicit Stack keeps a symbolic size on the stack as a variable-length array, whose bound is Max(1, size) because a zero-length VLA is undefined. Lifetimes that outlive the block and split declarations still use the heap.
ipow.eval folds whenever base and exponent are numbers, integral or not; only a negative numeric exponent is refused. Both test files call every test from their __main__ block.
Conflicts take main's implementation where main already solves the problem: DefinedNames, typed DACE_* environment overrides, LoopToMap (#2502), map parameter type inference and the compiler driver. FaCe keeps the distributed_compile error broadcast and Python's % (PyMod). Removed from FaCe: the PMI/SIGCHLD build-environment workaround, the OMP_MAX_THREADS reserved symbol, the OpenMP simd map marking (Map.omp_simd, MarkSIMDMaps, compiler.cpu.simd_maps), compiler.cuda.emit_synchronization with its __DACE_NO_SYNC override, and the library nodes no dace-fortran application uses (BLAS Copy, Swap, Trsv, Trmv, Trsm, Trmm; LAPACK Geqrf, Orgqr, Potrs). Axpy is main's again.
Every shift reused one SDFG name, so a later case loaded the library an earlier shift had built and compared against the wrong rotation.
FaCe now carries #2515's implementation instead of its own copies.
…aring the size A shape given by a constant whose symbol has another dtype than the constant stayed symbolic after the constants check, so the size comparison raised on a sympy Relational (Polybench doitgen).
…main's config tests The guard rejected every non-str replacement, so a plain symbol rename from safe_replace left the old key in place (main's replace_symbol_types_test). The env-override tests went with the config.py change that main's #2602 replaced.
SpecializeMatMul matches on the squeezed operand sizes, but Gemm.validate, the GEMM code generation and Transpose re-read the raw subset. An operand such as the (NQ, 1, NP) reshape in doitgen reached Gemm and was rejected as not a matrix, and an (N, 1) or (1, N) array was rejected by Transpose because it was squeezed to rank 1. blas_helpers.matrix_view returns the raw subset when it is already 2D and the squeezed one otherwise, together with the dimensions it kept, so sizes and strides cannot disagree. matmul, gemm and transpose all read operands through it.
…te names The walk moves into PowerRelaxer, the sign facts of an SDFG become a frozen SignFacts that is passed down instead of saved and restored on the pass, and the provers are public functions that the tests call directly. Behaviour is unchanged.
… NORM2 and CSHIFT AllNode, AnyNode and CountLibraryNode reduce a mask, every non-zero value of which is true, with a Reduce node, whole-array or along one dim; All and Any also expand to a short-circuiting loop. ArgMin and ArgMax find the first (or, with back, last) index of the extreme element among those an optional mask selects. Norm2 sums squares and takes the root; CShift rotates along one dim. A nested array keeps the strides of the container its memlet reads.
…nsional, axis-batched, FFTW3 and hipFFT FFTs Scal, Symv, Symm and Syrk get a pure expansion and an OpenBLAS/MKL one, and Ger an OpenBLAS/MKL one (?geru for complex data, as Ger does not conjugate). A routine that updates an operand in place gets a copy of its input operand in dataflow first, and reads matrices in their own layout: row- or column-major with their leading dimensions, else the pure expansion. Dot takes conjugate (?dotc) and initializes a device result on the device. FFT and IFFT take axis, a batched one-dimensional transform. The pure expansion transforms N-dimensional arrays of any layout; cuFFT, hipFFT and FFTW3 plan C-ordered ones, and FFTW3 applies the normalization factor. MakePlan2d and MakePlan3d no longer get a batch count, which they do not take. numpy.fft.fft along any axis and numpy.fft.fftn lower to these nodes. General CI installs FFTW3.
…eads after it ScalarWriteShadowScopes walked a read's dominators for a writing state only, so a read after an if/else that writes the scalar in both arms found no write, counted as live-in, and kept every write in one scope. CloudSC's ZFAC/ZFACI stayed one container shared by three JL loops, and none of them mapped. Such a conditional now dominates the read; the final write of each branch joins one scope, so all arms write the version the read uses. (cherry picked from commit 9673588)
…e element they write The Python path matched only a binary operator, so ``a = max(a, x)`` and ``a = a or x`` (Fortran's MAX and .OR. accumulations) stayed plain writes and their loops stayed sequential. It also took any input connector as the accumulator, without the same-element check of the C++ path; an update now has to read the element it writes. (cherry picked from commit 96786cf)
isolate_tasklet named an undefined sdfg, so an update whose accumulator is written earlier in the same state raised NameError before the state fission it needs. (cherry picked from commit 196eb65)
…mbol uses The ordered walk handled a conditional's out-edges before the branches below it, so a symbol both arms assign and the edge after the conditional reads (CloudSC's ZFAC once fissioned per loop) counted as read before assignment. The None that results was also or-ed into a set before being checked, raising TypeError instead of refusing. A block now counts its own reads only (state dataflow, branch conditions, loop init/condition/update); its region's nested reads come with the nested blocks. (cherry picked from commit 437238d)
…out of the parent (cherry picked from commit e859362)
…ests (cherry picked from commit d5ef3cb)
…e scopes (cherry picked from commit 2dc6aab)
…and keep its tests ahead of __main__
# Conflicts: # tests/transformations/interstate/loop_to_map_test.py
# Conflicts: # dace/codegen/targets/framecode.py # dace/sdfg/state.py
# Conflicts: # dace/libraries/standard/nodes/__init__.py # dace/libraries/standard/nodes/argminmax.py # dace/libraries/standard/nodes/cshift.py # dace/libraries/standard/nodes/norm2.py # tests/library/argminmax_test.py # tests/library/cshift_test.py
# Conflicts: # dace/libraries/mpi/nodes/abort.py # dace/libraries/mpi/nodes/barrier.py # dace/libraries/mpi/nodes/bcast.py # dace/libraries/mpi/nodes/comm_f2c.py # dace/libraries/mpi/nodes/comm_rank.py # dace/libraries/mpi/nodes/comm_size.py # dace/libraries/mpi/nodes/comm_split.py # dace/libraries/mpi/nodes/gatherv.py
# Conflicts: # .github/workflows/general-ci.yml # dace/frontend/python/replacements/fft.py # dace/libraries/blas/blas_helpers.py # dace/libraries/blas/nodes/ger.py # dace/libraries/blas/nodes/scal.py # dace/libraries/blas/nodes/symm.py # dace/libraries/blas/nodes/symv.py # dace/libraries/blas/nodes/syrk.py # dace/libraries/fft/algorithms/dft.py # dace/libraries/fft/nodes/fft.py # tests/library/fft_test.py
A copy, transpose or reduction has a single tensor operand and its own library node, so lifting it to an Einsum only turned a Reduce into an Einsum that expands back into one. The lift tests now assert the reduction stays a Reduce, as on extended.
…fortran checks it as a build post-condition
s275's g = aa[0, i] guards the aa recurrence: demoted, its read merges with the recurrence's writes and the RAW hint is lost. A guard read from data nothing writes (CloudSC's iphase[jm]) demotes like any value, so the loops it guards still fuse. Ported from extended.
The s275 RAW hint is proven from the element accesses without it, and a guard kept as a symbol splits the loops it guards.
# Conflicts: # dace/libraries/standard/nodes/__init__.py # dace/libraries/standard/nodes/cshift.py # dace/sdfg/sdfg.py # dace/sdfg/utils.py # dace/transformation/passes/loop_local_memory_reduction.py # tests/library/cshift_test.py # tests/transformations/map_fusion_vertical_test.py
…e writes It compared only the subsets, so out = max(x, a) writing A[1] picked x when x read X[1].
It kept a copy of every symbol for every state it resolved: QE h_psi code generation held 14478 states of about 12500 symbols each, 15 GB, more than a CI runner has. Callers resolve one state's nodes together, so the last state per SDFG keeps the reuse; h_psi now generates the identical code in 1.4 GB.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft PR to run CI on the FaCe branch, based on main. Not for review yet.