仓库源文

.. 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封装里面就好了,封装一个回调,然后提供的基本是一样的功能,这个看不出价值 来。

最后我的建议就是:

  1. 仅封装UACCE内核接口

  2. 先做好一种加速器的模式,如果有模式类似的,他们自然会聚合的,不需要在没有新加 速器引入之前就YY一个接口出来

补充1:我解释一下把CPU用作加速器有什么好处。其实我觉得确实也没有什么好处,但如 果非要找出好处来,其实也是有的,专精的好处是没有调度成本。比如我留两个CPU出来专 门做浮点加速,那么我的主程序就没有浮点了,这样主程序调度就是是不需要保存FP寄存 器的。作为加速器的CPU就专门接收浮点计算任务,它也不需要保存浮点寄存器,因为他的 任务不是基于线程调度的,它的任务是基于一个个独立的请求来调度的,本来就是做完一 个再做下一个,这基本上是用到什么寄存器才保存什么寄存器,这个成本就降下来了。

这种收益不一定能足够大。我觉得这个问题值得讨论是因为:

  1. 它有利于理解作为协处理器和作为加速器的区别是什么。

  2. 如果需要,我们完全可以在没有加速器硬件的时候推演WarpDrive的所有功能。

  3. 未来我们做一些专用用途的核,比如带加密扩展指令或者CNN扩展指令的核,这些核可 以直接复用这个方案。有兴趣的高校实验室不妨和我们联系,我们觉得这会是一个代表 性的未来方向。

补充2:前面的抽象可能有点高,我说得更接地气一点。简单说,wd现在的架构是这样的:

    .. figure:: _static/wd3.jpg

有两个模块都需要知道设备的差异,中间的wd统一接口,横插了一杆子,做了一个强制的 统一,但这种统一并不带来工作量和性能上的有事。所以完全可以变成这样:

    .. figure:: _static/wd4.jpg

由于加速器可以抽象为一个线程,未来这里的某加速器通讯适配,可以标准化为某种线程 接口,这就是正文中的异构线程库的意义。但既是没有这个库,UACCE封装还是一样的封装 ,它就封装uacce在内核中抽象的功能。

这可能包括的东西会是:

  1. 设备查找,属性存取

  2. 队列打开和关闭(封装open和相关的fd属性设置,基本的ioctl过程)

  3. 标准队列功能封装(比如等待)

  4. Region维护和共享