Python Numba,奇怪的类型修改

Python Numba,奇怪的类型修改,python,numba,Python,Numba,我正试图进一步加快一些用python编写的代码的速度,这些代码是使用Numba编译的。当查看由numba生成的程序集时,我注意到生成了双精度操作,我觉得这很奇怪,因为输入和输出都应该是浮动的 我将变量/数组类型声明为jitted循环外部的float32,并将它们传递到函数中。奇怪的是,我发现在运行测试之后,变量“scalarout”被转换为python float,它实际上是一个64位的值 我的代码: from scipy import ndimage, misc import matplotl

我正试图进一步加快一些用python编写的代码的速度,这些代码是使用Numba编译的。当查看由numba生成的程序集时,我注意到生成了双精度操作,我觉得这很奇怪,因为输入和输出都应该是浮动的

我将变量/数组类型声明为jitted循环外部的float32,并将它们传递到函数中。奇怪的是,我发现在运行测试之后,变量“scalarout”被转换为python float,它实际上是一个64位的值

我的代码:

from scipy import ndimage, misc
import matplotlib.pyplot as plt
import numpy.fft
from timeit import default_timer as timer
import numba
# numba.config.DUMP_ASSEMBLY = 1
from numba import float32
from numba import jit, njit, prange
from numba import cuda
import numpy as np
import scipy as sp

# import llvmlite.binding as llvm
# llvm.set_option('', '--debug-only=loop-vectorize')

@njit(fastmath=True, parallel=False)
def mydot(a, b, xlen, ylen, scalarout):
    scalarout = (np.float32)(0.0)
    for y in prange(ylen):
        for x in prange(xlen):
            scalarout += a[y, x] * b[y, x]
    return scalarout

# ======================================== TESTS ========================================

print()
xlen = 100000
ylen = 16
a = np.random.rand(ylen, xlen).astype(np.float32)
b = np.random.rand(ylen, xlen).astype(np.float32)
print("a type = ", type(a[1,1]))
scalarout = (np.float32)(0.0)
print("scalarout type, before execution = ", type(scalarout))
iters=1000

time = 100.0
for n in range(iters):
    start = timer()
    scalarout = mydot(a, b, xlen, ylen, scalarout)
    end = timer()
    if(end-start < time):
        time = end-start
print("Numba njit function time, in us = %16.10f" % ((end-start)*10**6))
print("function output = %f" % scalarout)
print("scalarout type, after execution = ", type(scalarout))
从scipy导入ndimage,杂项
将matplotlib.pyplot作为plt导入
导入numpy.fft
从timeit导入默认\u计时器作为计时器
进口麻木
#numba.config.DUMP_程序集=1
从numba导入浮动32
来自numba进口jit、njit、prange
来自numba import cuda
将numpy作为np导入
将scipy作为sp导入
#将llvmlite.binding导入为llvm
#llvm.set_选项(“”,--debug only=loop vectorize’)
@njit(fastmath=True,parallel=False)
def mydot(a、b、xlen、ylen、scalarout):
scalarout=(np.float32)(0.0)
对于prange(伊伦)中的y:
对于prange中的x(xlen):
scalarout+=a[y,x]*b[y,x]
回程斜角窗
#============================================================测试========================================
打印()
xlen=100000
伊伦=16
a=np.random.rand(ylen,xlen).aType(np.float32)
b=np.random.rand(ylen,xlen).aType(np.float32)
打印(“a type=”,type(a[1,1]))
scalarout=(np.float32)(0.0)
打印(“scalarout类型,执行前=”,类型(scalarout))
iters=1000
时间=100.0
对于范围内的n(iters):
开始=计时器()
scalarout=mydot(a、b、xlen、ylen、scalarout)
结束=计时器()
如果(结束开始<时间):
时间=结束-开始
打印(“Numba njit功能时间,单位为us=%16.10f”((结束-开始)*10**6))
打印(“函数输出=%f”%scalarout)
打印(“scalarout类型,执行后=”,类型(scalarout))

这与其说是一个答案,不如说是一个延伸的评论。如果将
scalarout
更改为长度为1的float32数组并对其进行修改,则输出为float32

@njit(fastmath=True,parallel=False)
def mydot(a、b、xlen、ylen):
scalarout=np.array([0.0],dtype=np.float32)
对于prange(伊伦)中的y:
对于prange中的x(xlen):
scalarout[0]+=a[y,x]*b[y,x]
回程斜角窗
如果将
return scalarout
更改为
return scalarout[0]
,那么输出仍然是python浮点


mydot
的原始代码中,即使编写
返回np.float32(scalarout)
,结果也是python浮点。这是一个有趣的想法,并且它确实强制输出类型为np.float32。不幸的是,它会导致函数执行速度慢5倍。您可以使用
mydot.inspect\u types()
获取内部类型
scalarout=np.float32(0.)
或定义局部变量,例如
@njit(fastmath=True,parallel=False,局部变量={“scalarout”:numba.types.float32})
。只有5%的性能优势(该问题主要受内存带宽限制),由于精度较低导致的结果差异更为明显。