How to convert a non numba dictionary to a nb.typed.Dict?

Hi,

using numba 0.54, I would like to convert a normal python dictionary to a numba compatible dictionary.

My code is the following:

import time

import numba as nb
# @nb.jit(nopython=True, cache=True)
def getNumbaDictFromDict(myDict):
    returnDict = nb.typed.Dict.empty(
        key_type=nb.types.unicode_type,
        value_type=nb.types.float64, )
    for runner in range(len(list(myDict))):
        returnDict[list(myDict.keys())[runner]] = myDict[list(myDict.keys())[runner]]
    return returnDict

myDict = {'a': 14., 'b': 15., 'c': 16.}
my_time = time.time()
abc = getNumbaDictFromDict(myDict)
print('time:', time.time() - my_time)

print("abc=", abc)

It takes roughly 2 seconds to execute it. If I activate the numba compiler directive, I get an error message:

This error may have been caused by the following argument(s):
- argument 0: Cannot determine Numba type of <class 'dict'>

Is there anything I can do to avoid the 2 seconds I have to wait for every execution?

Thanks in advance!

1 Like

hi @alatif-alatif
is your goal to use a typed.Dict in regular python code (non-jitted)? Or would you pass returnDict to another jitted function later?

Hi @luk-f-a

I want to use returnDict, or better to say abc later on in another jitted function (@nb.jit(nopython=True, cache=True)).

thanks, I understand. The filling of the dictionary can be done in jitted code, when the source is an array, list, tuple, anything that can be passed into a jitted function. Python dictionaries cannot be passed to a jitted function, so filling the typed.Dict from a python dict can only be done in a normal function (so without the decorator as you found out).
The 2 seconds you mention are the result of having to compile the typed.Dict for your types. The cost will not be 2 seconds every time you run the function, only the first time. Look at the example below:

import time
import numba as nb
# @nb.jit(nopython=True, cache=True)
def getNumbaDictFromDict(myDict):
    returnDict = nb.typed.Dict.empty(
        key_type=nb.types.unicode_type,
        value_type=nb.types.float64, )
    for runner in range(len(list(myDict))):
        returnDict[list(myDict.keys())[runner]] = myDict[list(myDict.keys())[runner]]
    return returnDict
myDict = {'a': 14., 'b': 15., 'c': 16.}
# running first time
my_time = time.time()
abc = getNumbaDictFromDict(myDict)
print('time:', time.time() - my_time)
# running a second time
my_time = time.time()
abc = getNumbaDictFromDict(myDict)
print('time:', time.time() - my_time)
time: 2.0478579998016357
time: 0.0002455711364746094

hope this helps,
Luk

1 Like