代码是怎么到GPU的

在开始这一章节之前,决定先聊会儿闲天。作为一个技术文章,上来就讲技术的都是外行,那是代码辅导员,真正好的文章一定是先聊家常,慢慢把你引导故事内容当中来。我想你在看这本书的时候,也不可能是焚香沐浴,正襟危坐的一页一页翻看。如果真是这样,那绝对是我的失败。在我的期望中,读者都应该左手拿着烤羊腰子,右手拿着啤酒,享受着阅读我这个叨逼叨的玩意儿。有人说不能为了吃活着,真正高尚的人都是为了活着而吃,但我觉得真正的人生应该是且活且吃。

好了,道理我都懂,所以GPU是怎么获取instructions的?其实真正的答案是,我也不知道。真的气啊,找了一天资料,没有一个GPU生产厂家说过这个事儿。我就不明白了,这个东西能算做机密吗?我一气之下就通过driver逆向猜测了一下这个过程,仅仅是写出来防止自己忘了给大家分享一下。但是要注意两点,一是这个是我喝着啤酒瞎猜出来了,二是这个只是Mali GPU的一个方案。

首先讲一下大约的思路,当用户说要执行一个GPU代码的时候,用户会给driver一个地址,这个地址就指向了这段代码,当然是GPU的机器码。然后driver会把这个地址写到GPU的寄存器上,然后driver会告诉GPU,下来接客(差点涉黄啊)来任务了,GPU就会通过DMA把这段代码读到一个叫做Job Manager的地方,这个Job Manager是GPU上物理存在的一个东西,而且里面应该有个instruction memory。

当然GPU也不是你让他干啥,他就立马去干啥,在Mali的一个PPT里(真的找的我心累啊)提到过有在硬件眼里有三种jobs,分别是 Vertex Job(V), Tiler Job(T) 和 Fragment Job(F)。相应的,在driver向GPU提交任务的时候,可以指定一个Job Slots,可能的值是0,1,2。如果你坚信这是一个巧合,那么。。。好吧,你不能认为这是个巧合,这意味着GPU里能同时存分别调度的3种任务,并且这三种任务有自己的priority。

具体到代码上来呢,当一切都准备就绪,压倒GPU的最后一根稻草就是一个叫kbase_job_hw_submit的函数。这个函数首先回去看JS_COMMAND_NEXT这个寄存器是不是空,如果是,那么机器码的地址的头就会被写进寄存器里。经过一些无聊的操作之后,driver会给这个任务,啪的一声,打上一个时间戳。在设置好很多trace函数之后,driver会写JS_COMMAND_NEXT这个寄存器写上一个START,这个任务就进入ALU的汪洋大海当中了。

当然这里我漏掉了一个细节,就是一个job slot到底能放多少个job(s)?很遗憾我现在还不知道,但我知道怎么去知道,所以之后我就会去知道知道。