NP的C语言编译器

Sina WeiboBaiduLinkedInQQGoogle+RedditEvernote分享




下面我来尝试探讨softmaster提出问题:
(1)为何没有见到用C语言编写NP代码的?
(2)C语言编译器还不成熟、不实用,主要原因在于NP的编程模型是“并行多线程”的,对吗?
(3)可否通过“增加微引擎的个数”来解决这个问题?

第一个问题,为何没有见到用C语言编写NP代码的?

我认为现在NP的C语言编译器还不成熟,还不能实用。相对于汇编语言来说,高级语言的主要优点是:(a)编程效率高,开发生产率高;(b)代码可移植。缺点是:运行效率低。对于NP来说,C语言编译器的优点并不明显,缺点却特别突出。

先说编程效率。NP上面运行的代码量并不大,典型NP的代码空间是几K到几十K条指令,也就是一个产品的NP代码不会特别多。一般高端路由器产品,NP代码总量也不过几百K条指令,这个规模的程序,用汇编语言也可以完成,障碍不大。

插一点题外话。NP开发的难度不是由于代码量大,而在于对人员的知识和能力要求高。例如,NP的开发人员需即要能够深入理解NP的硬件结构,要熟练掌握汇编语言开发,还要理解网络协议报文的处理流程(例如要掌握MPLS的工作原理),而且还有懂一点硬件知识(至少要会用示波器)。这样的人不太好找。这一点与很多其他程序开发不同。

再谈可移植性。NP程序几乎天生不具有可移植性,即便用高级语言也不能移植。由于目前各个厂商之间的NP的结构几乎完全不同(试比较IXP2xxx、X11、EZChip NP2/3),NP程序又是跟芯片紧密耦合在一起的,因为必须利用芯片提供的各种硬件资源(如查表、HASH、mem IO等)才能够提高效率。甚至一个同一个厂商的不同型号的NP之间,程序的可移植性都很差。

最后说运行效率。NP程序的运行主要是由报文触发的,收到了报文才运行。虽然NP的代码空间有几K到几十K指令,但并不是说对于每个报文,都能够用几十K代码去处理。一般来说,NP只允许对每个报文运行几十到几百条指令,超过这个数量,就无法达到“线速处理”这个硬指标了。例如:某型号NP有8个微引擎,核心运行速度是600M,并且每周期运行一条指令,又假设该NP有一个2.5G POS接口,全是最小报文的测试情况下,报文流入NP的速度大约是8M pps(packet per second),那么对于一个报文来说,允许每个微引擎的运行的处理指令最多是:600M / 8M,大约为70几条,8个微引擎加起来,在指令分配非常均衡的情况下,最多600条指令。以上都是按照理想情况考虑的,如果再去掉跳转、IO等待、ME之间处理能力分配不均衡等因素,那么实际对每个报文允许的处理指令可能也就是300条左右。在要求的线速处理路径上,如何用这300条指令来完成所有的业务处理,是需要仔细计算的。几乎不能容忍高级语言编译器再浪费一些指令。

由此可见,也许在未来的很长一段时间内,我们还要用汇编语言来编NP程序。

下面把第二个问题和第三个问题合并到一起分析。NP的的编译器的确还不成熟,但是主要不是因为“多线程”。

对多数硬件支持的多线程芯片(CPU、NPU)来说,是由几套寄存器上下文共享一个ALU处理逻辑,在软件看来,就像是芯片里面有几个硬的“核”一样,没什么大分别。因此“多线程”也不会显著增加编译器的设计难度。

下面尝试分析一下多线程和大规模多核两种不同的NP设计思路。

芯片支持的多线程和多核的目标都是:充分利用硅片面积来提高单芯片的处理性能。但是方法不同。

多线程的依据是:现在CPU/NPU的核心速度很快,但是DRAM的访问速度很慢(注1),因此很多时候,快速运行的CPU/NPU核心不得不等待内存访问完成,浪费了大量的处理能力。解决办法是,为一套运算部件多配几套寄存器,每套寄存器都保存一个线程上下文,当一个线程访问外部内存不得不等待的时候,就运行另外一个线程。这样运算部件的利用提高了。一般来说,多线程CPU/NPU的的每个核都比较复杂,运行频率也比较高,如果频率低于内存访问时间,多线程就没有多大意思了。

对多线程来说,虽然运算部件的利用率较高,但是每套寄存器都会占用一定的面积,而且同时只能有一套寄存器处于运行状态,另外几套都是处在等待状态,还是有浪费。大规模多核NPU/CPU(注2)的设计者思路就不同,他们在芯片里面造很多个简单的核,每个核的频率都不高,占用面积也比较小,每个时刻每个核都在运行,争取让每个晶体管都工作起来。大规模多核芯片会尽可能用比较简单的、低成本的方法把这些核组织起来。NP的报文驱动的应用模式,恰好为组织这些核提供了方便,Xelerated和EZchip都巧妙的利用了这一点。

多线程和大规模多核那种设计方法更好,现在似乎还没有绝对公认的结论。但我估计,未来在NP领域大规模多核会越来越多。

(结束)

注1: 虽然现在DDR3看起来速度已经达到了上GHz的级别,但是这是假象,只有访问连续的地址单元才能够达到这个速度。如果访问的地址单元不连续,则DRAM的瓶颈在于其tRC这个参数,一般只有几十纳秒。
注2:如Tilera的Tile64、Xelerated X10q/11、EZChip NP1c/2/3等。

(2个打分, 平均:5.00 / 5)

雁过留声

“NP的C语言编译器”有3个回复

  1. asic 于 2008-12-21 4:05 上午

    曾经有个小公司做了teja的工具是C编译器么.

  2. softmaster 于 2008-12-21 6:45 上午

    多谢黄岩的这篇评论,把我想问而没问出来的问题总结了出来。不过对于第一个和第二个问题,我还有些不同的看法。

    本文的一个观点我十分赞同:”相对于汇编语言来说,高级语言的主要优点是:(a)编程效率高,开发生产率高;(b)代码可移植。缺点是:运行效率低。”

    从我个人角度而言,对于NP来说,C语言编译器的优点十分明显,缺点却未必突出。

    先说编程效率:C语言的开发效率远远高于汇编语言,这一点应该没有异议吧。我们有一个经验数据,对于一个基于IXP的使用汇编语言开发的NP模块,一个工程师大概需要6个月的时间才能写出优质代码。而对于一个使用C语言开发的应用模块,基本上1个月不到就可以了(注1)。此外,从代码的维护角度,C语言也比汇编语言要有效率的多。只根据代码量来看开发的effort是不太准确的。例如:开发相同功能的两个NP团队,一个使用汇编语言,一个使用C语言。如果前者需要6个工程师左右,则后者可能只需要3个工程师了。

    其次,因为NP都是自定义的指令集。对于NP编译器/调试器的开发,因为没有编译器前端的代码可共享,汇编语言的编译器工作量显然要大于C语言。而使用C语言来编码的话,就有大量的开源软件来重用。例如:借用GCC的前端来生成编译器。利用DDD来调试微码(注2)。

    此外,C语言还有很多好处。例如第三方的代码检查工具,自动化测试脚本生成工具等等。都可以大大提高基于C语言编码的开发效率。

    再说可移植性,两者都严重依赖芯片的体系结构,不同芯片之间的代码基本上谈不上可移植性。大哥不说二哥,彼此,彼此。

    最后说执行效率。一般而言,汇编语言的编程效率要高于C语言,这点我同意。但是对于NP代码的开发而言,未必。首先,NP的代码开发只是进行报文处理,所以不需要调用标准库. 其次,我们可以在编码中使用一些特定编程技巧来规避消耗cycle数的C语言语句。例如:可以使用inline函数来避免不必要的函数开销, 使用表驱动的函数指针方式来替代case语句等等。最后,编译器在某些方面可以做的比人工更好。例如:跳转语句的等待延时的利用,全局寄存器的统一分配与释放等等。(注3)

    所以用C语言来编程是大势所趋,在NP编程领域,一定会替代汇编语言。也许这个过程现在已经开始了:)

    那么说了这么多C语言编程的好处,为什么很多网络处理器还用汇编编程呢?可能是网络处理器厂商的编译器团队能力还不够吧,玩笑话:)。主要是C语言本身不支持多线程编程模型。如果是JAVA,就没有这个问题了,可JAVA又太高级了,这个面向对象的开销还是NP所浪费不起的。如果C语言不支持多线程,那么必须由编译器来自动完成。让编译器来选择何时切换/释放处理器资源,这个估计目前的编译器的水平还达不到。

    注1:两者开发的都是具体的业务逻辑,并没有涉及到过多的硬件细节。此外,我对黄岩提到的NP工程师需要会使用示波器这点很好奇,能不能具体解释一下。
    注2:在这里DDD无法进行指令集级别的模拟和调试,只能进行C语言级别的功能调试。而这对于大部分情况而言,足够用了。
    注3:对编译器我是外行,以上全是猜测。这方面陈首席是专家,可以指点一下。

  3. 陈怀临 于 2008-12-21 8:28 上午

    1. 是的。NP芯片公司很难养一个编译器团队。这方面的人也非常少。
    2. 性能问题主要是函数调用,堆栈约定等带来的。所以设计NP的编译器要对寄存器的使用比较熟练,避免过多使用内存做堆栈链,如PowerPC的EABI等。
    3.从我的经验看,效率能压在小于等于5%左右。也就是说,不会影响整体性能。
    4.当然,不同的NP不同。
    5.有也是为什么QuantumFlow等一上,ASR1000的Deep Inspection能飞起来的原因。否则,写微码做IDS是不可能的。
    6。可编程的网络服务处理器是大势所趋。。。