Configuring DaCe

Various aspects of DaCe can be configured through a YAML file called .dace.conf, through DACE_* environment variables, or through the configuration API. DaCe does not create or modify a configuration file on its own — save() writes one explicitly — with one exception: a configuration file in the old format (which stored every entry) is rewritten once, when first loaded, to the current format that keeps only the entries changed from their defaults.

Note

Documentation for all configuration entries is available at the Configuration entry reference.

DaCe reads at most one configuration file, the first one found: a .dace.conf in the current working directory, then the file pointed to by the DACE_CONFIG environment variable, then .dace.conf in the user’s home directory. If none exists, the schema defaults are used.

An example configuration file, which changes two configuration entries, looks as follows:

compiler:
  cuda:
    default_block_size: 64,8,1  # Change GPU map block size

debugprint: true  # Add more verbosity in printouts

When compiling programs, the configuration used to build it will also be saved along with the binary in the appropriate .dacecache folder. The configuration file in that folder contains all configuration entries, not just the ones changed from default, for reproducibility purposes.

Changing configuration entries via environment variables

Any configuration entry can be overridden using environment variables. To do so, create a variable that starts with DACE_ followed by the configuration entry path. Dot (.) characters should be replaced with _.

Environment variables are read once, when the configuration is loaded (at import time, or on an explicit load()); their values are coerced to the entry’s declared type. Changing a DACE_* variable afterwards has no effect until the configuration is reloaded, and values set through the API always take precedence over the environment.

For example, setting the CPU compiler path (compiler.cpu.executable) with an environment variable can be done as follows:

$ export DACE_compiler_cpu_executable=/path/to/clang++
$ python my_program_with_clang.py

Getting/setting configuration entries via the API

Within DaCe, obtaining or modifying configuration entries is performed by accessing the dace.config.Config singleton.

Get and set values with get() and set(). For boolean values, use get_bool() to convert more options (e.g., 1, True, yes) to booleans. If the setting is in a hierarchy, pass it as separate arguments. Examples include:

from dace.config import Config

print('Synchronous debugging enabled:', Config.get_bool('compiler', 'cuda', 'syncdebug'))

Config.set('frontend', 'unroll_threshold', value=11)

We also provide a context manager API to temporarily change the value of a configuration (useful, for example, in unit tests, where configuration changes must not persist outside of a test):

# Temporarily enable profiling for one call
with dace.config.set_temporary('profiling', value=True):
    dace_laplace(A, args.iterations)

Deciding the value of a configuration entry

If an entry is defined in multiple places, its value is decided when the configuration is loaded, with the following sources in increasing priority:

  1. The default value from the configuration schema

  2. The configuration file (the first one found, see above)

  3. A DACE_* environment variable

Values set through the API afterwards (set(), set_temporary(), temporary_config()) have the highest priority, since the environment is only consulted while loading. Loading does not write the configuration file (apart from the one-time migration of old-format files noted above), so neither environment values nor API changes end up in .dace.conf unless save() is called explicitly.

Useful configuration entries

General configuration:

Profiling:

  • profiling: Enables profiling measurement of the DaCe program runtime in milliseconds. Produces a log file and prints out median runtime. See Profiling and Instrumentation for more information.

  • treps: Number of repetitions to run when profiling is enabled.

GPU programming and debugging:

  • compiler.cuda.backend: Chooses the GPU backend to use (can be cuda for NVIDIA GPUs or hip for AMD GPUs).

  • compiler.cuda.syncdebug (default: False): If True, calls device-synchronization after every GPU kernel and checks for errors. Good for checking crashes or invalid memory accesses.