Python中的脉动阵列仿真
我试图在Python环境中模拟矩阵乘法的脉动数组结构——所有这些都是我从这些幻灯片中学到的。脉动数组不可分割的一部分是PE之间的数据流与任何一个节点上发生的任何乘法或加法并发。我很难猜测如何准确地在Python中实现这样一个并发过程。具体地说,我希望更好地理解一种计算方法,即以级联方式将要相乘的矩阵元素馈送到脉动数组中,同时允许这些元素以并发方式在数组中传播 我已经开始用python编写一些代码,将两个3乘3的数组乘以,但最终,我想模拟任意大小的脉动数组,以处理任意大小的a和b矩阵Python中的脉动阵列仿真,python,multithreading,signal-processing,simulation,vlsi,Python,Multithreading,Signal Processing,Simulation,Vlsi,我试图在Python环境中模拟矩阵乘法的脉动数组结构——所有这些都是我从这些幻灯片中学到的。脉动数组不可分割的一部分是PE之间的数据流与任何一个节点上发生的任何乘法或加法并发。我很难猜测如何准确地在Python中实现这样一个并发过程。具体地说,我希望更好地理解一种计算方法,即以级联方式将要相乘的矩阵元素馈送到脉动数组中,同时允许这些元素以并发方式在数组中传播 我已经开始用python编写一些代码,将两个3乘3的数组乘以,但最终,我想模拟任意大小的脉动数组,以处理任意大小的a和b矩阵 from t
from threading import Thread
from collections import deque
vals_deque = deque(maxlen=9*2)#will hold the interconnections between nodes of the systolicarray
dump=deque(maxlen=9) # will be the output of the SystolicArray
prev_size = 0
def setupSystolicArray():
global SystolicArray
SystolicArray = [NodeSystolic(i,j) for i in range(3), for i in range(3)]
def spreadInputs(a,b):
#needs some way to initially propagate the elements of a and b through the top and leftmost parts of the systolic array
new = map(lambda x: x.start() , SystolicArray) #start all the nodes of the systolic array, they are waiting for an input
#even if i found a way to put these inputs into the array at the start, I am not sure how to coordinate future inputs into the array in the cascading fashion described in the slides
while(len(dump) != 9):
if(len(vals_deque) != prev_size):
vals = vals_deque[-1]
row = vals['t'][0]
col = vals['l'][0]
a= vals['t'][1]
b = vals['l'][1]
# these if elif statements track whether the outputs are at the edge of the systolic array and can be removed
if(row >= 3):
dump.append(a)
elif(col >= 3):
dump.append(b)
else:
#something is wrong with the logic here
SystolicArray[t][l-1].update(a,b)
SystolicArray[t-1][l].update(a,b)
class NodeSystolic:
def __init__(self,row, col):
self.row = row
self.col = col
self.currval = 0
self.up = False
self.ain = 0#coming in from the top
self.bin = 0#coming in from the side
def start(self):
Thread(target=self.continuous, args = ()).start()
def continuous(self):
while True:
if(self.up = True):
self.currval = self.ain*self.bin
self.up = False
self.passon(self.ain, self.bin)
else:
pass
def update(self, left, top):
self.up = True
self.ain = top
self.bin = left
def passon(self, t,l):
#this will passon the inputs this node has received onto the next nodes
vals_deque.append([{'t': [self.row+ 1, self.ain], 'l': [self.col + 1, self.bin]}])
def returnValue(self):
return self.currval
def main():
a = np.array([
[1,2,3],
[4,5,6],
[7,8,9],
])
b = np.array([
[1,2,3],
[4,5,6],
[7,8,9]
])
setupSystolicArray()
spreadInputs(a,b)
上面的代码不可操作,仍然有许多bug。我希望有人能给我一些建议,告诉我如何改进代码,或者是否有一种更简单的方法用Python中的异步属性对脉动数组的并行过程进行建模,因此对于非常大的脉动数组,我不必担心创建太多的线程节点。考虑在Python中模拟脉动数组是很有趣的,但我认为按照上面所画的思路进行模拟会有一些很大的困难 最重要的是,Python在真正的并行性方面的范围有限,这是由。这意味着,对于计算受限的任务,您不会获得任何显著的并行性,其线程可能最适合处理I/O受限的任务,例如web请求或文件系统访问。最接近Python的方法可能是通过模块实现,但这需要对每个节点进行单独的处理 其次,即使要在systolic数组中的数值运算中获得并行性,也需要一些机制来允许不同线程在尝试同时读取和写入数据时交换数据或消息,而不会损坏彼此的内存 关于示例中的数据结构,我认为最好让脉动数组中的每个节点都引用其上游节点,而不是知道它位于NxM网格中的特定位置。我不认为脉动数组需要是矩形网格的任何理由,任何有向无环图DAG都仍然有可能实现高效的分布式计算
总体上,我希望在Python中进行这种仿真的计算开销相对于使用诸如斯卡拉或C++之类的低级语言可以实现的巨大。即使如此,除非脉动阵列中的每个节点都在进行大量计算,即远多于几次乘法相加,否则节点之间交换消息的开销将是巨大的。因此,我认为您的模拟主要是为了了解数据流和阵列的高级行为,而不是为了接近定制DSP数字信号处理硬件提供的功能。如果是这样的话,那么我会尝试不使用线程,而是使用一个集中式消息队列,所有节点都向该队列提交由全局消息分发机制传递的消息。
是有道理的,事实上就是这样。我更感兴趣的是制作一个python模拟来可视化数据传播。用C++,有没有办法绕过任何全局解释器锁来实现真正的并行性,所以仿真可以更好地模拟真正的收缩阵列?你知道Python、C++或其他语言中的收缩阵列的任何仿真程序吗?