はじめに
Numbaで扱える変数の型については、主な対象は数値とNumPy配列 (numpy.ndarray) だがそれ以外にもいろいろある。
しかしそれらは使用方法や型指定方法が公式ドキュメントに整備されていないので各種型の使用方法と型指定方法を試して結果をまとめた。
多くは公式ドキュメントに書かれていないため筆者が手元で試した結果をまとめたものです。
応用的な型の型指定方法については公式ドキュメントに書かれている範囲でさえ安定版でないと書かれています。
普通に関数を@jit
で高速化する使い方であれば型指定なしの @jit(nopython=True, cache=True)
でよく、型指定に速度上のメリットはないと思われます (以前の記事)。
型指定は jitclass, AOTコンパイル, objmode などで必要です。
Numbaで型指定を与えるには方法が何通りかあります。
-
numba
モジュール内のNumba型指定オブジェクトを与える -
numba.typeof
関数から得られるNumba型指定オブジェクトを与える - 文字列で与える
これらのうち typeof
関数はたいていの場合に便利ですが一部の型を表現できません。
また、jitclassの型指定は文字列で与えられないようです。
記事中では理解しやすさを優先し、モジュールのインポート名を原則フルパスにしました。実際に使うときは使いやすい名前をインポートすることをすすめます。
検証環境 (両方で確認):
- Python 3.12.5, NumPy 1.26.4, Numba 0.60.0
- Python 3.11.3, NumPy 1.24.3, Numba 0.57.0
目次を兼ねた要約
-
1. 数値型(真偽値型含む):
numba.boolean
,numba.uint64
,numba.int64
,numba.float64
など -
11. jitclassインスタンスオブジェクト :
MyJitclass.class_type.instance_type
0. たいていの型指定を簡便に可能な typeof
関数
numba.typeof
関数に対象の値を与えるとたいていの場合は適切な型指定オブジェクトが得られる。
ただし一部にtypeof関数で指定できない型がある(後述)
動作確認コード
import numpy as np
import numba
print(f"{numba.typeof(3.14) == numba.float64 =}") # True
print(f"{numba.typeof(1) == numba.int64 =}") # True
print(f"{numba.typeof(True) == numba.boolean =}") # True
print(f"{numba.typeof(None) == numba.void =}") # True
print()
print(
f"""{numba.typeof(np.ones((4,3,2,),dtype=np.float64))
== numba.types.Array(numba.float64, 3, 'C')
=}""")
# True
print()
tuple_of_4 = 1.11, 1, False, np.array([[1.11]], dtype=np.float64)
print(f"{tuple_of_4 =}") #
print(f"""{numba.typeof(tuple_of_4)
== numba.types.Tuple((
numba.float64, numba.int64, numba.boolean, numba.types.Array(numba.float64, 2, 'C'),
))
=}""")
# True
1. 数値型(真偽値型含む): numba.boolean
, numba.uint64
, numba.int64
, numba.float64
など
基本の数値型の型指定は公式ドキュメントに説明あり。
一覧表にすると以下になる
Python組み込み型 | NumPy型 | Numba型指定オブジェクト | Numba型指定文字列 |
---|---|---|---|
bool |
numba.boolean , numba.bool_ , numba.b1
|
boolean , bool_ , b1
|
|
int |
numba.int64 , numba.i8
|
int64 , i8
|
|
float |
numba.float64 , numba.f8
|
float64 , f8
|
|
complex |
numba.complex128 , numba.c16
|
complex128 , c16
|
|
numpy.bool_ |
numba.boolean , numba.bool_ , numba.b1
|
boolean , bool_ , b1
|
|
numpy.uint8 |
numba.uint8 , numba.u1
|
uint8 , u1
|
|
numpy.uint16 |
numba.uint16 , numba.u2
|
uint16 , u2
|
|
numpy.uint32 |
numba.uint32 , numba.u4
|
uint32 , u4
|
|
numpy.uint64 |
numba.uint64 , numba.u8
|
uint64 , u8
|
|
numpy.int8 |
numba.int8 , numba.i1
|
int8 , i1
|
|
numpy.int16 |
numba.int16 , numba.i2
|
int16 , i2
|
|
numpy.int32 |
numba.int32 , numba.i4
|
int32 , i4
|
|
numpy.int64 |
numba.int64 , numba.i8
|
int64 , i8
|
|
numpy.float32 |
numba.float32 , numba.f4
|
float32 , f4
|
|
numpy.float64 |
numba.float64 , numba.f8
|
float64 , f8
|
|
numpy.complex64 |
numba.complex64 , numba.c8
|
complex64 , c8
|
|
numpy.complex128 |
numba.complex128 , numba.c16
|
complex128 , c16
|
真偽値の型名がまちがえやすい。
数値型の型指定はエイリアスが多い。
数値型の型指定オブジェクトは numba.XXX
と同等なものが numba.types.XXX
にもある模様。
import numba
print(f"""{numba.typeof(3.14)
== numba.float64
== numba.f8
== numba.types.float64
== numba.types.f8
=}""")
# True
print(f"""{numba.typeof(True)
== numba.boolean
== numba.bool_
== numba.b1
== numba.types.boolean
== numba.types.bool_
== numba.types.b1
=}""")
# True
(補足: NumPy 2.0 では 真偽値の型名は numpy.bool
が正式名になり、それまでの正式名numpy.bool_
はエイリアスになるとのこと (NumPy公式) 。
ただし少し前のNumPyでは numpy.bool
はPython組み込み bool
のエイリアスで、 numpy.bool_
とは別物だったので注意)
2. NumPy配列
2-1. NumPy配列-簡易指定: 中身の型+スライス記号
数値型の型指定にスライス記号を付ければNumPy配列の型指定になる。公式。
例えばfloat64の配列で、1次元なら numba.float64[:]
、2次元なら numba.float64[:,:]
、3次元なら numba.float64[:,:,:]
。
ただし、この記述方法はメモリレイアウト指定なしの簡易指定になり、たいていの場合は問題ないが一部の使い方でコンパイルエラーになった。詳細と対応は次項で説明。
2-2. NumPy配列-メモリレイアウト配置を指定: スライス表記末尾を::1
もしくは numba.types.Array(中身の型, 次元数, "C")
前項の簡易指定による型指定は普通に生成したNumPy配列を typeof
に渡したときの型指定と厳密には異なる模様。
型指定オブジェクトを print
すると詳細を確認でき、簡易指定のものは A
、typeof
したものは C
と確認できる。
大抵の状況では簡易指定で A
と指定した場所へ C
のデータを与えても動作した (C
はC言語式メモリレイアウト、A
はAnyを意味するとのこと)。
ただし一部の用途では A
と C
の違いが吸収されずコンパイルエラーになった。(後述のコードなど)
その場合に以下のようにすると C
レイアウトで型指定でき、エラーを予防できた。
- ダミーで作成したNumPy配列を
numba.typeof
関数に与える (簡単) - スライス記号で最後の次元を
::1
とする。例えば、- float64の1次元なら
numba.float64[::1]
- float64の2次元なら
numba.float64[:,::1]
- float64の3次元なら
numba.float64[:,:,::1]
- float64の1次元なら
- NumPy配列用型指定オブジェクト生成関数
numba.types.Array(中身の型, 次元, "C")
で明示的に指定する。例えば、- float64の1次元なら
numba.types.Array(numba.float64, 1, "C")
- float64の2次元なら
numba.types.Array(numba.float64, 2, "C")
- float64の3次元なら
numba.types.Array(numba.float64, 3, "C")
- float64の1次元なら
型指定の動作確認コード
外部リンク
3. None型とOptional型
3-1. None型: numba.void
もしくは numba.none
関数が返り値なしの時に。
3-2. Optional型(Noneともう一つ型の両方に対応): numba.optional(もう一つの型)
numbaは静的型付けコンパイルを行うため、原則コンパイル時に変数の型が決定していなければならないが、None型だけは他の型との混在が許される模様。
そのような変数を扱う際は if x is None: (Noneの場合の処理) else: (もう一つの型の場合の処理)
のようにチェックしてから処理すると動いてくれる (明確に分岐内で処理しないとエラーになりやすい)。
軽く速度を測定したところ、単純な数値型の関数で同等のif文を伴った場合と同程度であった。
関数に@jit
する場合などは型指定なしでもOptional型に型推論してくれる。jitclassなど型指定が必要な場合は numba.optional(もう一つの型)
と指定する。
これは typeof
関数では指定できない模様。
jitclassで型指定の動作確認
外部リンク
4. タプル
NumbaのタプルはPythonのそれと異なり、コンパイル時に中身の数と各型が決定している必要がある。
そのためかNumba関数内でのタプル生成はカンマ区切り記法のみで、tuple
関数は使えない。
いくつかの例で速度を測ったところNumPy配列と同等以上に速かった。
4-1. (異種型混合可能な)タプル: numba.types.Tuple((中身の型0, 中身の型1, 中身の型2, ...))
要素の数はいくつにも指定可能、異なる型の混在OK。
型指定の方法は、例えば3要素のタプルだと
-
typeof
関数 (簡単) - 型指定オブジェクト生成関数
numba.types.Tuple((中身の型0, 中身の型1, 中身の型2))
- 文字列方式での型指定は
Tuple((中身の型0, 中身の型1, 中身の型2))
丸括弧が二重になることに注意。
typeof
関数を使った場合、次のUniTuple
が使用可能な場合はUniTuple
を優先して出力し、混合時のみTuple
になる模様。
import numba
print(f"""{numba.typeof((1.11, 2,))
== numba.types.Tuple((numba.float64, numba.int64,))
=}""")
# => True
4-2. 中身の型が統一されたタプル: numba.types.UniTuple(中身の型, 個数)
要素の型が統一されている場合こちらも使える。
型指定の方法は、
-
typeof
関数 (簡単) - 型指定オブジェクト生成関数
numba.types.UniTuple(中身の型, 個数)
- 文字列方式での型指定は
UniTuple(中身の型, 個数)
import numba
print(f"""{numba.typeof((1.11, 2.22, 3.33, 4.44, 5.55,))
== numba.types.UniTuple(numba.float64, 5)
=}""")
# => True
動作確認コード
jitclassで型指定の動作確認
外部リンク
5. リスト系コンテナ
個数の不定なデータを格納するのに適したリストだが、現在のNumbaでは可変長コンテナ類は開発途上なうえリストだけで数種類あり得意不得意が分かれている。
いずれも中身の型は統一されている必要がある。
気づきにくい注意点がいろいろありエラーに悩まされやすい。
todo: Numbaで可変長コンテナを使うときの注意点をまとめた記事を別に作る
5-1. reflected-list-(reflected=True): numba.types.List(中身の型, reflected=True)
使用方法
- Python領域でPython組み込み
list
を作成し、中身のある状態でNumba関数へ引数渡しする
型指定
-
typeof
関数に中身のあるlist
を与える(簡単) - 型指定オブジェクト:
numba.types.List(中身の型, reflected=True)
- 文字列方式での型指定:
List(中身の型, reflected=True)
特徴
- 処理速度を測定すると、NumPy配列には負けるものの、Pythonのlistから大幅に高速化された
-
可変長コンテナ類との入れ子が不可能、例えば2重リストなどができない
- "Numpy配列を要素とするリスト" は可能で、これなら異なる長さの配列を格納できた
- この場合の型指定はレイアウト
C
を指定する必要があった (レイアウトA
がエラーになった)
- この場合の型指定はレイアウト
- "Numpy配列を要素とするリスト" は可能で、これなら異なる長さの配列を格納できた
- 要素数が多いとPythonの
list
から変換されるとき少し変換時間が発生した - Numba化関数の返り値でPython領域に返すとPython組み込み
list
に逆変換された - Numba化関数内でリストをin-place変更すると、変更内容が元のPythonの
list
に反映された (これがreflect動作) - 使用すると
NumbaPendingDeprecationWarning
警告が発生する(非表示にはできる)
5-2. reflected-list-(reflected=False): numba.types.List(中身の型, reflected=False)
Python領域で生成したリストを引数渡ししたものとNumba化関数内で生成したリストで扱いが異なる。
使用方法
- Numba化関数内で角括弧
[]
記法やlist
関数を用いてリストを作成 + 型推論させる - なお、Numba化関数内での ndarray.tolist() メソッドは未実装
- Numba化関数の返り値でPython領域に返すとPython組み込み
list
に変換され、元に戻せなくなる模様
型指定
- 型指定オブジェクト:
numba.types.List(中身の型, reflected=False)
、numba.types.List(中身の型)
- 文字列方式での型指定:
List(中身の型, reflected=False)
,List(中身の型)
-
typeof
関数では指定できない模様
特徴
- 処理速度を測定するとNumPy配列には負けるものの、Pythonのlistから大幅に高速化された
- reflected-list-(reflected=False) 同士や reflected-set-(reflected=False) との多重コンテナが可能
- 辞書系コンテナとの多重コンテナはできなかった (次項のtyped-listを使うことになる)
- 入力データをPython領域からNumba化関数内へ持ち込む方法を工夫する必要がある
- 使用すると
NumbaPendingDeprecationWarning
警告が発生する (非表示にはできる) - 現時点でのリスト系コンテナではこれが一番速いと思われる
- デバッグがやややりにくい
5-3. typed-list: numba.types.ListType(中身の型)
使用方法
- Python領域もしくはNumba関数内で、以下のtyped-list生成関数を使用 (2つは同等) + 型推論させる
numba.typed.typedlist.List
numba.typed.List
- Python領域もしくはNumba関数内で、以下の型指定付きtyped-list生成関数に型を渡す (2つは同等)
numba.typed.typedlist.List.empty_list(中身の型)
numba.typed.List.empty_list(中身の型)
型指定
- typed-listを生成し、中身の型を確定させた後、
typeof
関数に渡す - 型指定オブジェクト:
numba.types.ListType(中身の型)
- 文字列方式での型指定:
ListType(中身の型)
特徴
- 今のところ開発途上で、処理速度を測定すると素のPythonのlistからそれなりに高速化するもののreflected-listに劣った
- typed-list 同士や typed-dict との多重コンテナが可能
- reflected-listと異なり、Python領域とNumba化関数内の間で受け渡しても変換なし
- typed-listをPython領域内で動作させたときの処理速度は遅かった
動作確認コード
Numbaのリスト3種が区別されることの確認
import numba
@numba.jit(nopython=True)
def type_checker_1(arg):
return arg
# Python領域のpython-listをNumba化関数へ与える
pylist = [1.11, 2.22, 3.33]
type_checker_1(pylist)
print(f"{type_checker_1.signatures =}")
# => [(List(float64, True),)]
@numba.jit(nopython=True)
def type_checker_2(arg):
return arg
# Numba化関数内で角括弧記法でリストを生成
@numba.jit(nopython=True)
def make_reflectedlistFalse(n):
reflectedlistFalse = [i * 1.11 for i in range(n)]
type_checker_2(reflectedlistFalse)
make_reflectedlistFalse(3)
print(f"{type_checker_2.signatures =}")
# => [(List(float64, False),)]
@numba.jit(nopython=True)
def type_checker_3(arg):
return arg
# typed-list生成関数で生成
typedlist = numba.typed.List([1.11, 2.22, 3.33])
type_checker_3(typedlist)
print(f"{type_checker_3.signatures =}")
# => [(ListType(float64),)]
jitclassで型指定の動作確認
-
1重リスト
-
2重リスト
6. 辞書系コンテナ
Numba は Python 組込のdict
に非対応。Python領域からNumba関数に与えても型指定に関係なく拒否される。
import numba
@numba.jit(nopython=True)
def receiver(arg):
return arg
pydict = {1: 1.11, 2: 2.22, 3:3.33}
try:
res = receiver(pydict)
print(res)
except Exception as e:
print(type(e), e)
# => Pythonのdictは受け入れ拒否される
# <class 'numba.core.errors.TypingError'> Failed in nopython mode pipeline (step: nopython frontend)
# non-precise type pyobject
# - argument 0: Cannot determine Numba type of <class 'dict'>
Numba 関数内で dict を作ろうとすると後述の typed-dict が生成する(リスト、セットと挙動が異なる)。
typed-dict という Numba 独自のデータ構造があり、Numba化関数内で辞書系コンテナを使うにはこれを使う。しかし、開発途上で素のPython-dictよりほとんど速くならない。
高速化のためには辞書そのものを避けたいところ。
さらに、リスト同様にいろいろ注意点がありエラーに悩まされやすい。
6-1. typed-dict: numba.types.DictType(キーの型, バリューの型)
使用方法
- Python領域もしくはNumba関数内で、以下のtyped-dict生成関数を使用(2つは同等) + 型推論させる
numba.typed.typeddict.Dict()
numba.typed.Dict()
- Python領域もしくはNumba関数内で、以下の型指定付きtyped-dict生成関数に中身の型を渡す(2つは同等)
numba.typed.typeddict.Dict.empty(キーの型, バリューの型)
numba.typed.Dict.empty(キーの型, バリューの型)
- Numba化関数内で波括弧
{}
記法 やdict
関数で辞書を生成 + 型推論させる- 辞書内包表記を使える。内包表記を使うと型推論を失敗しにくい
- 問題が起こったときのデバッグがやややりにくい
型指定
-
typeof
関数に中身の型が決定済のtyped-dictを渡す - 型指定オブジェクト:
numba.types.DictType(キーの型, バリューの型)
- 文字列方式での型指定:
DictType(キーの型, バリューの型)
特徴
- Numba化関数内で辞書を使うにはこれ
- typed-listとの多重コンテナ可能
- 変換なしにPython領域とNumba化関数内でデータを受け渡しできる
- 処理速度を測定すると、Numba化関数内のtyped-dictでも素のPythonの
dict
とあまり変わらなかった - typed-dictをPython領域で動作させるとかなり遅かった
動作確認コード
Numba用辞書は numba.typed.Dict
使用とNumba化関数内での波括弧記法で同種のものが生成する
import numba
@numba.jit(nopython=True)
def type_checker_1(arg):
return arg
# Python領域でtyped-dict生成関数を使用して生成
typeddict_in_py = numba.typed.Dict()
typeddict_in_py[1] = 1.11
typeddict_in_py[2] = 2.22
type_checker_1(typeddict_in_py)
print(f"{type_checker_1.signatures =}")
# => [(DictType(int64, float64),)]
@numba.jit(nopython=True)
def type_checker_2(arg):
return arg
# Numba化関数内でtyped-dict生成関数を使用して生成
@numba.jit(nopython=True)
def make_typeddict_in_numba_explicitly(n):
typeddict_in_numba_explicitly = numba.typed.Dict()
typeddict_in_numba_explicitly[1] = 1.11
typeddict_in_numba_explicitly[2] = 1.11
type_checker_2(typeddict_in_numba_explicitly)
make_typeddict_in_numba_explicitly(3)
print(f"{type_checker_2.signatures =}")
# => [(DictType(int64, float64),)]
@numba.jit(nopython=True)
def type_checker_3(arg):
return arg
# Numba化関数内で波括弧記法で辞書を生成
@numba.jit(nopython=True)
def make_typeddict_in_numba_by_braces(n):
typeddict_in_numba_by_braces = {i: i * 1.11 for i in range(n)}
type_checker_3(typeddict_in_numba_by_braces)
make_typeddict_in_numba_by_braces(3)
print(f"{type_checker_3.signatures =}")
# => [(DictType(int64, float64),)]
jitclassで型指定の動作確認
外部リンク
7. 集合系コンテナ
集合系コンテナは現在のNumbaでは reflected-set 系統のみ。
将来的には "typed-set" を実装してそちらに切換える計画とのことだが未実装。
やはりいろいろ注意点がありエラーに悩まされやすい。
開発途上で素のPythonからわずかしか速くならない。
またfrozensetには未対応な模様。Python領域からNumba化関数に与えても指定に関係なく拒否された。
7-1. reflected-set-(reflected=True): numba.types.Set(中身の型, reflected=True)
使用方法
- Python領域でPython組み込み
set
を作成し、Numba関数へ引数渡しする
型指定
-
typeof
関数に中身のあるsetを与える(簡単) - 型指定オブジェクト
numba.types.Set(中身の型, reflected=True)
- 文字列方式での型指定は
Set(中身の型, reflected=True)
特徴
- 可変長コンテナ類との入れ子が不可能、例えばsetをlistに格納してPython領域から渡すと拒否された
- 要素数が多いとPythonのsetから変換されるとき少し変換時間が発生した
- Numba化関数の返り値でPython領域に返すとPython組み込みsetに逆変換された
- Numba化関数内でセットをin-place変更すると、変更内容が元のPythonのsetに反映された (これがreflected動作らしい)
- 使用すると
NumbaPendingDeprecationWarning
警告が発生する(非表示にはできる)
7-2. reflected-set-(reflected=False): numba.types.Set(中身の型, reflected=False)
Python領域で生成したセットを引数渡ししたものとNumba化関数内で生成したセットで扱いが異なる。
使用方法
- Numba関数内で角括弧
{}
記法やset
関数を用いてセットを作成する - Numba化関数の返り値でPython領域に返すとPython組み込みsetに変換され、元に戻せなくなる
型指定
- 型指定オブジェクト:
numba.types.Set(中身の型, reflected=False)
、numba.types.Set(中身の型)
- 文字列方式での型指定:
Set(中身の型, reflected=False)
、Set(中身の型)
-
typeof
関数では指定できない模様
特徴
- 処理速度を測定すると、素のPythonの
set
よりわずかに速い程度だった - reflected-list-(reflected=False) に格納できた (多重コンテナ)
- 入力データをPython領域からNumba化関数内へ持ち込む方法を工夫する必要がある
- 使用すると
NumbaPendingDeprecationWarning
警告が発生する(非表示にはできる)
jitclassで型指定の動作確認
8. 文字列(str): numba.types.unicode_type
使用方法
- Python領域のstrをNumba化関数へ引数渡しする
- Numba化関数内で文字列リテラルや
str
関数を使用して生成
型指定
- typeof関数を利用
- 型指定オブジェクト:
numba.types.unicode_type
,numba.types.string
- 文字列方式では:
unicode_type
,string
速度が遅い機能があちこちにあるので、むしろNumba化関数内で文字列を不用意に使わないように注意
さらに文字列から数値への変換 int(s: str)
などが未実装のため使う機会は少なそう
数値から文字列への変換 str(x)
は、整数系は成功したが、float系はエラーにならないものの適切な表記が得られなかった
9. バイト列系シーケンス
bytesやそれをNumPy配列に格納したものを扱えた。
bytearrayやmemoryviewも扱えた。
9-1. バイト列(bytes): numba.types.Bytes(numba.uint8, 1, "C")
使用方法
- Python領域のbytesをNumba化関数へ引数渡しできた
- Numba化関数内でバイト列リテラルで生成可能
- なお、Numba化関数内での
bytes
関数を試してみたがエラーになった - また、Numba化関数内での
ndarray.tobytes()
メソッドは未実装だった
型指定
- typeof関数を利用
- 型指定オブジェクト
numba.types.Bytes(numba.uint8, 1, "C")
- 文字列方式では
Bytes(uint8, 1, "C")
注意点
- Numba関数内で使えるメソッドがかなり少ない
- 試した範囲では
.startswith
,.endswith
, スライス,np.frombuffer
などはできた
- 試した範囲では
9-2. bytearray: numba.types.ByteArray(numba.uint8, 1, "C")
- Python領域から引数渡しできた
- Numba化関数内での
bytearray
関数を試してみたがエラーになった - 型指定オブジェクト:
numba.types.ByteArray(numba.uint8, 1, "C"),
9-3. memoryview: numba.types.MemoryView(numba.uint8, 1, "C", readonly=True)
- Python領域から引数渡しできた
- Numba化関数内での
memoryview
関数を試してみたがエラーになった - 型指定オブジェクト:
numba.types.MemoryView(numba.uint8, 1, "C", readonly=True)
型指定の動作確認コード
10. Numba化関数オブジェクト
Numba化関数の引数として別のNumba化関数を関数オブジェクトとして渡せる。
詳しくは以前の記事
コンパイル時に固定される関数オブジェクトの型指定
Numba化関数オブジェクトを引数に渡すときの型指定は、関数名をmyjitfunc
とした場合、次のいずれでも得られた。
numba.typeof(myjitfunc)
myjitfunc._type
-
myjitfunc._numba_type
関数宣言後ならコンパイル前でも型指定オブジェクトがとれた。
ただし、このやり方は入出力型が同一型の個別の関数は別々の型と見なされた。
関数の@jit
で型指定しなければ気にする必要はないが、 jitclass や AOT で引数に関数オブジェクトを渡して処理の一部を切り換えさせるような利用法は次の入れ替え対応の型指定をする必要があると思われる。
関数オブジェクトをコンパイル後に入れ替えさせたい場合の型指定 numba.types.FunctionType(返り値の型(引数の型のタプル))
- 型指定オブジェクト:
numba.types.FunctionType(返り値の型(引数の型のタプル))
- 型指定文字列:
FunctionType(返り値の型(引数の型のカンマ区切り))
typeof
関数では得られない
関数オブジェクトを入れ替え可能にするならこちらの型指定方法で。
todo: 入れ替え可能にして処理速度が低下しないか測定する
古いNumbaには無いようで、Numba 0.49 からソースコード (*.py の class * ) に分岐の追加を確認できる
11. jitclassインスタンスオブジェクト : MyJitclass.class_type.instance_type
jitclassのインスタンス変数の型として他種のjitclassインスタンスを指定するときなどに。
型指定オブジェクトの取得は次のいずれでも得られた:
- クラス名を
MyJitclass
とした場合MyJitclass.class_type.instance_type
numba.extending.as_numba_type(MyJitclass)
- Python領域に生成したインスタンス名を
myins
とした場合numba.typeof(myins)
myins._numba_type_
typeof
関数に与えられるのはインスタンス。クラスを与えるとエラーになったので注意。
Numbaの質問サイトやコード例では基本的に MyJitclass.class_type.instance_type
が使用されていた。
12. 再帰的な型指定のための、後で定義するNumba型 : numba.deferred_type()
連結リストノードや木構造ノードなど再帰的な型をjitclass化しようとすると、jitclassの定義時開始時に自身の型を指定することが必要になる。
このような状況は numba.deferred_type()
を使うと具体的な型指定を後回しにできるので解決する。
終わり
Numbaは数値型、NunPy配列、タプル以外もいろいろな型を使える。
ただし注意点が増えるし、速度を確認していない型を使うと高速化を損ねるおそれがある。
optional型, reflected-list あたりは速度もかなり出るのでNumPy配列では不向きな処理に採用してよさそう。
型指定は全般的にややこしい。
また、一部の型は typeof
関数で指定できない。
参考
https://numba.readthedocs.io/en/stable/reference/pysupported.html
https://stackoverflow.com/questions/53900084/problem-with-reflected-list-signature-in-numba
https://computational-sediment-hyd.hatenablog.jp/entry/2020/07/16/200000