我刚开始学习Numba来加速for循环。我读到它是impossible to call a non-jitted function from a numba jitted function。因此我不认为我可以@jitclass(spec)
我的类或@njit
主算法函数(compute()
)让我的代码保持原样,因为模拟的每一步(onestep()
)也会改变图像tkinter.Photoimage
中像素的值,这是一个Python类型。
- 对程序进行任何可能的逻辑变更,将GUI和数字部分充分分离,以允许应用Numba;
- 是否有与Numba兼容的Tkinter替代品;
- 除了Numba还有什么别的选择我可能会从中受益。
下面是我代码的简化版本:
import tkinter as tk
import numpy as np
window = tk.Tk()
window.geometry("600x600")
canv_w= 480
square_w = 16 #size of one element of the matrix
canvas=tk.Canvas(window,width=480,height=480)
canvas.pack()
my_image=tk.PhotoImage(width=480,height=480)
canvas.create_image((3, 3),image=my_image,anchor="nw",state="normal")
running =0
def pixel(self, i,j):
if self.matrix[i,j]==-1:
temp="#cc0000" #red
elif self.matrix[i,j]==0:
temp= "#fffafa" #white
elif self.matrix[i,j]==1:
temp="#7CFC00" #green
my_image.put(temp,to=(i*square_w,j*square_w,(i+1)*square_w,(j+1)*square_w))
class myClass:
def __init__(self, size):
self.L=size
self.matrix=np.random.choice([-1, 0, 1], (self.L,self.L), p=[0.45,0.1,0.45])
self.white_number=len(np.where(self.matrix==0)[0])
self.iteration=0
for i in range(self.L):
for j in range(self.L):
pixel(self,i,j)
def onestep(self):
whites=np.where(self.matrix==0)# find position of all white squares
my_v= np.random.choice(self.white_number)# randomly pick one white square...
x=whites[0][my_v]
y=whites[1][my_v]
num= np.random.choice([0,1,2,3]) #...randomly pick one of its 4 neighbours
neighbour=[[(x + 1)% self.L, y], [x, (y + 1) % self.L], [(x - 1)% self.L, y], [x, (y - 1)% self.L]]
#swap with neighbour
self.matrix[x,y]=self.matrix[neighbour[num][0],neighbour[num][1]]
self.matrix[neighbour[num][0],neighbour[num][1]]=0
pixel(self,x,y) #update the pixel the white square has left
pixel(self,neighbour[num][0],neighbour[num][1]) #update the pixel the white atom has jumped to
def compute(self):
if running:
for j in range(1, self.white_number + 1):
self.onestep()
self.iteration+=1
window.after(1000,self.compute)
running=1
myObj=myClass(30)
myObj.compute()
window.mainloop()
1条答案
按热度按时间ymdaylpp1#
cython是存在的,并且比numba更成熟,但是它需要编译器,所以你只需要编译二进制文件,而不是JIT函数,它提供静态类型,并且消除了解释器的开销。
实际上,您可以使用numbaobjmode调用一个非JIT编译的函数,但它仍然有一些约束,请考虑将每个JIT编译的函数拆分为一个可JIT编译的部分和一个不可JIT编译的部分,如下所示
这里,
onestep
没有被即时修正,而执行重负载的_onestep
被即时修正。在你的程序中有一些加速(每帧有numba的11毫秒对没有numba的19毫秒),因为大部分时间花在绘图上,而不是计算上,所以它不会从任何更多的“编译”中受益。
更好的方法是将所有的屏幕数据存储为2d数组,并在numba中操作它,然后在python中一次重绘整个屏幕,而不是一部分一部分地重绘。
cython可能能够从中获得更多优化的代码,因为它可以在同一个函数中混合python和非python对象,并消除循环开销,但为它编写代码比numba更难。