ฉันจะระบุสิ่งอันดับในลายเซ็น Numba Vectorize ได้อย่างไร

ฉันกำลังกำหนดฟังก์ชันและต้องการใช้ Numba Vectorize เพื่อเร่งความเร็วด้วย cuda ฉันมีปัญหากับลายเซ็นของฟังก์ชัน ฟังก์ชันจะส่งกลับค่า float64 ฉันต้องการส่งค่า float64 สองค่าซึ่งจะเป็นค่า vectorized และนอกเหนือจากค่า float64 9 tuple ซึ่งจะเป็นสเกลาร์

นี่คือส่วนหัวฟังก์ชันของฉัน:

from numba import vectorize

@vectorize(['float64(float64, float64, UniTuple(float64, 9))'], target='cuda')
def fn_vec(E, L, fparams):
    # calculations... 
    return result

แต่สิ่งนี้ทำให้เกิดข้อผิดพลาด:

TypeError: data type "(float64 x 9)" not understood

ฉันได้ลองใช้รูปแบบต่างๆ มากมาย รวมถึง (float64, ..., float64) แทนที่ UniTuple() แต่ไม่สามารถทำอะไรได้เลย ฉันจะทำอย่างไร?


person kevinea    schedule 19.04.2019    source แหล่งที่มา


คำตอบ (1)


ฉันจะระบุสิ่งอันดับในลายเซ็น Numba Vectorize ได้อย่างไร

ในฟังก์ชัน numba.vectorize คุณไม่สามารถใช้สิ่งอันดับได้ นั่นเป็นเพราะว่า vectorize ทำเวคเตอร์โค้ดสำหรับอาร์เรย์ประเภทเหล่านี้

ดังนั้นการใช้ลายเซ็น float, float, tuple จะสร้างฟังก์ชันที่คาดว่าจะมีอาร์เรย์สองตัวที่มีโฟลตและอีกหนึ่งอาร์เรย์ที่มีสิ่งอันดับ ปัญหาคือไม่มี dtype สำหรับอาร์เรย์ที่มี tuples - มันสามารถทำงานได้หากคุณใช้อาร์เรย์ที่มีโครงสร้างแทนอาร์เรย์ที่มี tuples แต่ฉันไม่ได้ลอง

ฉันจะระบุสิ่งอันดับในลายเซ็น Numba jit ได้อย่างไร

วิธีที่ถูกต้องในการระบุ UniTuple ในลายเซ็น numba คือการใช้ numba.types.containers.UniTuple ในกรณีของคุณ:

nb.types.containers.UniTuple(nb.types.float64, 9)

ดังนั้นลายเซ็นที่ถูกต้องจะเป็นดังนี้:

import numba as nb

@nb.njit(
    nb.types.float64(
        nb.types.float64, 
        nb.types.float64, 
        nb.types.containers.UniTuple(nb.types.float64, 9)))
def func(f1, f2, ftuple):
    # ...
    return f1

ฉันมักจะหลีกเลี่ยงการพิมพ์ฟังก์ชัน numba ของฉันอย่างชัดเจน แต่เมื่อฉันทำ ฉันพบว่าการใช้ numba.typeof มีประโยชน์มาก ตัวอย่างเช่น:

>>> nb.typeof((1.0, ) * 9)
tuple(float64 x 9)

>>> type(nb.typeof((1.0, ) * 9))
numba.types.containers.UniTuple

>>> help(type(nb.typeof((1.0, ) * 9)))  # I shortened the result:
Help on class UniTuple in module numba.types.containers:

class UniTuple(BaseAnonymousTuple, _HomogeneousTuple, numba.types.abstract.Sequence)
 |  UniTuple(*args, **kwargs)
 |  
 |  Type class for homogeneous tuples.
 |  
 |  Methods defined here:
 |  
 |  __init__(self, dtype, count)
 |      Initialize self.  See help(type(self)) for accurate signature.

ข้อมูลทั้งหมดก็อยู่ที่นั่น: มันคือ numba.types.containes.UniTuple และคุณยกตัวอย่างด้วยอาร์กิวเมนต์สองตัว นั่นคือ dtype (ในที่นี้คือ float64) และตัวเลข (ในกรณีนี้คือ 9)

ในกรณีที่คุณต้องการสร้างเวคเตอร์บนอาร์เรย์โฟลตเท่านั้น

หากคุณไม่ต้องการสร้างเวกเตอร์ให้กับฟังก์ชันสำหรับอาร์กิวเมนต์ tuple คุณสามารถสร้างฟังก์ชัน vectorized ภายในฟังก์ชันอื่นแล้วเรียกมันที่นั่น:

import numba as nb
import numpy as np

def func(E, L, fparams):
    @nb.vectorize(['float64(float64, float64)'])
    def fn_vec(e, l):
        return e + l + fparams[1]  # just to illustrate that the tuple is available
    return fn_vec(E, L)

สิ่งนี้ทำให้ทูเพิลพร้อมใช้งานภายในฟังก์ชัน vectorized อย่างไรก็ตาม มันจะต้องสร้างฟังก์ชันภายในและคอมไพล์มันทุกครั้งที่คุณเรียกใช้ฟังก์ชันภายนอก ดังนั้นนี่อาจจะช้ากว่าจริงๆ ฉันไม่แน่ใจด้วยว่าจะใช้ได้กับ target="cuda" คุณอาจต้องทดสอบด้วยตัวเอง

person MSeifert    schedule 20.04.2019
comment
ขอบคุณสำหรับการตอบรับ น่าเสียดายที่สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันใช้ @vectorize ไม่ใช่ @njit บางทีนั่นอาจเป็นเหตุผล? ฉันพยายาม@nb.vectorize( nb.types.float64( nb.types.float64, nb.types.float64, nb.types.containers.UniTuple(nb.types.float64, 9))) def fn_vec2(E, L, fparams): # calcs... return Eแต่ได้TypeError: 'Signature' object is not iterable - person kevinea; 21.04.2019
comment
Vectorize คาดว่าจะมีลายเซ็นที่สามารถทำซ้ำได้ คุณลืมรายการที่อยู่รอบๆ ลายเซ็นแล้วหรือยัง? - person MSeifert; 21.04.2019
comment
คุณพูดถูก ฉันลืมรายการ ตอนนี้มัณฑนากรของฉันคือ @nb.vectorize([nb.types.float64( nb.types.float64, nb.types.float64, nb.types.containers.UniTuple(nb.types.float64, 9))]) และฉันได้รับข้อผิดพลาด NotImplementedError: (float64 x 9) ไม่สามารถแสดงเป็น Numpy dtype` - person kevinea; 18.05.2019
comment
@kevinea คุณช่วยยกตัวอย่างเล็ก ๆ ว่าคุณจะเรียกใช้ฟังก์ชันได้อย่างไร ฉันถูกต้องไหมที่คุณเรียกมันว่าประมาณนี้: fn_vec(np.ones(10), np.ones(10), tuple(np.ones(9))) - person MSeifert; 18.05.2019
comment
ใช่แล้ว ถูกต้องเลย และขอขอบคุณอีกครั้งสำหรับการตอบกลับ! - person kevinea; 19.05.2019
comment
ขอบคุณสำหรับการทำงานในเรื่องนี้ ตัวอย่างของคุณใช้งานได้จริงตอนนี้ แต่อย่างที่คุณสงสัยว่ามันค่อนข้างช้าเมื่อฟังก์ชัน vectorize อยู่ในฟังก์ชันภายใน ฉันยืนยันว่าใช้งานได้ และ target="cuda" ก็ใช้งานได้เช่นกัน - person kevinea; 23.05.2019