Is 1 dispatcher object (eager - given signature) for multiple functions safe?

I have a family of functions, each with the same signature.
Is it safe to use 1 dispatcher object for eager compilation?
E.g., which of the following options is safer or does it even matter?

A:

from numba as nb

dispatcher = nb.njit(nf.f8[:](nb.f8[:]))

@dispatcher
def square(x):
    return x**2

@dispatcher
def cube(x):
    return x**3

B:

from numba as nb

@nb.njit(nf.f8[:](nb.f8[:]))
def square(x):
    return x**2

@nb.njit(nf.f8[:](nb.f8[:]))
def cube(x):
    return x**3

Assume my functions square,cube are dynamically created in a factory, arbitrary amount.

What you sketch out for “A” is safe, but you’re not creating a single dispatcher. There’s no established terminology for what you’re doing, but I’d describe it as creating a specialized jit decorator.

We can see that the specialized decorator still creates individual dispatchers for each function:

import numba as nb

dispatcher = nb.njit((nb.f8[:],))


@dispatcher
def square(x):
    return x**2

@dispatcher
def cube(x):
    return x**3


print(dispatcher)
print(square)
print(cube)

gives:

<function _jit.<locals>.wrapper at 0x7856875e2340>
CPUDispatcher(<function square at 0x785687283ec0>)
CPUDispatcher(<function cube at 0x7855d12989a0>)

Note that dispatcher is a function, and square and cube are distinct dispatcher objects.

1 Like

Thank you for the clarification!