.. Kenneth Lee 版权所有 2019-2020
:Authors: Kenneth Lee :Version: 1.0
WarpDrive用户态方案重构建议
维护WarpDrive用户态部分的兄弟让我总结一下对用户态方案的发展策略建议,这个本来就是 开放项目,我就懒得发邮件发来发去了,直接在这里写。
现在WarpDrive的开放核心都放在uacce上,保证先可以上传内核再说。在uacce一侧,我们 在保证的是“让加速器和进程有相同的地址空间”。图示是这样:
.. figure:: _static/wd.jpg
uacce是维护一个框架,利用MMU和IOMMU的同步,让OS对进程的谎言,同时对加速器中的同 一进程成立。
也就是说,进程代表的是CPU,加速器代表的是另一个CPU,你可以认为它是偏房(CPU是正 房)。它们本质上没有什么区别,提供的都是计算能力。我甚至可以直接让渡几个CPU当做 加速器来使用(参考补充1)。如果加速器的指令(比如考虑它是一个GPGPU)也在进程的 地址空间中,那么,加速器,不过是执行一个异构线程。
所以,一种理想的软件方案是这样的:::
def algo2():
data2 = do_algo2_with_uacce_language()
return data2
def main_cpu():
data1 = algo1()
thread = create_acce_thread()
start_acce_thread(acce, algo2, data1)
data3 = algo3()
data2 = thread.join()
data = reduce(data2, data3)
return data;
当然,直接这样干最大的问题是编译器要同时认识多种编程语言,但在实际使用的时候只 要把编译器分开,到链接阶段再结合就好了。不会是非常大的问题。早期阶段我们甚至可 以直接把加速器的代码直接作为二进制打包到一个section里面就可以了。(这种简单的技 巧后面就不再提了,变通不是我们方案的重点,只是强调说我们是可以变通的。比如不支 持编程的加速器完全可以模拟成只有一条指令的线程就好了)
如果基于这个的基础推演,我们现在看第二个问题:每种加速器的通讯接口可能是不一样 的,我们在哪里封装这个不同?换句话说,我们是否需要为所有的加速器提供一个共同的 开发库,这个共同的开发库应该提供什么功能?
我们先用简单的的功能聚合来考量我们的方案,我们可以这样安排接口:
.. figure:: _static/wd2.jpg
其中“异构线程库”和“UACCE封装都是”我们说的“公共开发库”。这个看起来最大的问题是“ 异构线程库”太薄了,使用接口的用户又不能只看它,还是要理解加速器的行为。我们其实 可以用一个“开发指导”来取代这个库,可以建议加速器适配代码怎么开发,其他封装,放 到uacce封装里面就好了,封装一个回调,然后提供的基本是一样的功能,这个看不出价值 来。
最后我的建议就是:
仅封装UACCE内核接口
先做好一种加速器的模式,如果有模式类似的,他们自然会聚合的,不需要在没有新加 速器引入之前就YY一个接口出来
补充1:我解释一下把CPU用作加速器有什么好处。其实我觉得确实也没有什么好处,但如 果非要找出好处来,其实也是有的,专精的好处是没有调度成本。比如我留两个CPU出来专 门做浮点加速,那么我的主程序就没有浮点了,这样主程序调度就是是不需要保存FP寄存 器的。作为加速器的CPU就专门接收浮点计算任务,它也不需要保存浮点寄存器,因为他的 任务不是基于线程调度的,它的任务是基于一个个独立的请求来调度的,本来就是做完一 个再做下一个,这基本上是用到什么寄存器才保存什么寄存器,这个成本就降下来了。
这种收益不一定能足够大。我觉得这个问题值得讨论是因为:
它有利于理解作为协处理器和作为加速器的区别是什么。
如果需要,我们完全可以在没有加速器硬件的时候推演WarpDrive的所有功能。
未来我们做一些专用用途的核,比如带加密扩展指令或者CNN扩展指令的核,这些核可 以直接复用这个方案。有兴趣的高校实验室不妨和我们联系,我们觉得这会是一个代表 性的未来方向。
补充2:前面的抽象可能有点高,我说得更接地气一点。简单说,wd现在的架构是这样的:
.. figure:: _static/wd3.jpg
有两个模块都需要知道设备的差异,中间的wd统一接口,横插了一杆子,做了一个强制的 统一,但这种统一并不带来工作量和性能上的有事。所以完全可以变成这样:
.. figure:: _static/wd4.jpg
由于加速器可以抽象为一个线程,未来这里的某加速器通讯适配,可以标准化为某种线程 接口,这就是正文中的异构线程库的意义。但既是没有这个库,UACCE封装还是一样的封装 ,它就封装uacce在内核中抽象的功能。
这可能包括的东西会是:
设备查找,属性存取
队列打开和关闭(封装open和相关的fd属性设置,基本的ioctl过程)
标准队列功能封装(比如等待)
Region维护和共享