---
# System prepended metadata

title: DaCe issues / open problems

---

# DaCe issues / open problems
### Lifetime / Compliation as a service
- How do we do ahead of time compilation of sdfg's with limited lifetime?
```
import numpy as np

from fv3core.decorators import computepath_function, computepath_method


def plain_numpy(receive_slice, receive_buffer):
    receive_slice[:] = np.reshape(receive_buffer, receive_slice.shape)


def run2():
    receive_slice = np.random.rand(12, 3, 79)
    receive_buffer = np.zeros((receive_slice.size,))

    for _ in range(0, 10):

        @computepath_function(load_sdfg="")
        def func():
            plain_numpy(receive_slice, receive_buffer)

        func()

    # real example: in the call method of AcousticDynmaics 
    # we have computepath functions and the call to AcousticDynmaics 
    # happens in a loop outside.
    # Outside is not possible for escaping the language or with user facing code
    # can't deteriorate performance if looped


if __name__ == "__main__":
    run2()
```
---
### Explicit computepaths
- Instead having to pass explicit path's to the computepath, can we have it determined based on the cache at runtime?
```
import numpy as np

from fv3core.decorators import computepath_function, computepath_method


def plain_numpy(receive_slice, receive_buffer):
    receive_slice[:] = np.reshape(receive_buffer, receive_slice.shape)


def run3():
    receive_slice = np.random.rand(12, 3, 79)
    receive_buffer = np.zeros((receive_slice.size,))

    # can we dynamically load the sdfg from the known path?
    @computepath_function(load_sdfg=True)
    def func():
        plain_numpy(receive_slice, receive_buffer)

    for _ in range(0, 10):
        func()

if __name__ == "__main__":
    run3()

```
---
### Performance Numbers
- We do not have halo numbers just yet

---
### At scale compilation
- Our implementation of disributed compilation has only one directory
    - how do we get rid of the read / write conflicts if all ranks create their sdfgs?
- how can we have parallelism in the JIT compilation? is everything blocked by one thread doing compilation?


#### Dace Flow:
 1. `computepath_function` called at import time
 2. `LazyComputepathFunction.__init__` returns a `dace.program` from the `func`.
     * Sets `_sdfg_loaded=False` and `_sdfg=None`
3. `computepath_function` decorated methods on `corners.py` of `fv3core` are loaded first:
```
computepath_function._decorator: return LazyComputepathFunction(fill_nw_corner_agrid, use_dace=False, skip_dacemode=False, load_sdfg=None)
computepath_function._decorator: return LazyComputepathFunction(fill_se_corner_agrid, use_dace=False, skip_dacemode=False, load_sdfg=None)
computepath_function._decorator: return LazyComputepathFunction(fill_ne_corner_agrid, use_dace=False, skip_dacemode=False, load_sdfg=None)
...
```
4. Decorators on nested functions are decorated when the outer method is called.
```
return LazyComputepathFunction(func, use_dace=False, skip_dacemode=False, load_sdfg=)
```
5. Different code path when used with `kwargs`, returns decorator function rather than calling it.
```
    if len(args) == 1 and not kwargs and callable(args[0]):
        return _decorator(args[0])
    else:
        return _decorator
```
6. `LazyComputepathFunction.__call__` is invoked when decorated `func` is called.
7. If `use_dace` is `True`, SDFG is generated via the `LazyComputepathFunction.__sdfg__` method.
```
if self.use_dace:
    sdfg = self.__sdfg__(*args, **kwargs)
```
8. If `_load_sdfg`, convert `daceprog` object to to SDFG, otherwise load existing SDFG, either from file (if `_load_sdfg` is a valid file path), or from a precompiled SDFG.
```
                if os.path.isfile(self._load_sdfg):
                    self.daceprog.load_sdfg(self._load_sdfg, *args, **kwargs)
                else:
                    self.daceprog.load_precompiled_sdfg(
                        self._load_sdfg, *args, **kwargs
                    )
                self._sdfg_loaded = True
```
9. However, `load_precompiled_sdfg` also expects a path,
```
csdfg = sdutil.load_precompiled_sdfg(path)
```
  * Note: this is the crossover point from `fv3core` into `dace`.

---
### Function not registered with an SDFG implementation (DaceSyntaxError)

```
21:47:00         elif not found_ufunc:
21:47:00             func = oprepo.Replacements.get(funcname)
21:47:00             if func is None:
21:47:00 >               raise DaceSyntaxError(
21:47:00                     self, node, 'Function "%s" is not registered with an SDFG '
21:47:00                     'implementation' % funcname)
21:47:00 E               dace.frontend.python.common.DaceSyntaxError: Function "state.__dict__.update" is not registered with an SDFG implementation
21:47:00 E                 in File /scratch/snx3000/olifu/jenkins_submit/workspace/fv3core-acoustics-dace-test/action/verification/backend/gtc_dace/experiment/c12_6ranks_standard/orchestration/dace/slave/daint_submit/fv3core/stencils/dyn_core.py, line 458:8
21:47:00 
21:47:00 test_env/lib/python3.8/site-packages/dace/frontend/python/newast.py:3990: DaceSyntaxError