【学术论文】Go语言在国产CPU平台上应用前景的探索与思考

摘要: 代表信息新时代的Go语言诞生了,它所具有的高并发性非常适合服务器编程,而其天生的跨平台优势,降低了分布式异构计算平台的开发难度,最终让程序变得简洁、干净、高效。对Go语言在国产平台上的移植进行探索,实测Go语言在龙芯和飞腾两个国产平台的多核调用功能,分析研判结果,得出结论,为未来Go语言在国产平台的发展提供参考。

0 引言

CPU是电子产品的核心,代表着信息产业的发展水平。CPU发展至今已经有四十多年的历史了,实际就是Intel公司的发展历史[1]。Intel的CPU和其兼容产品占领了PC的大半江山。我国CPU战略已经发展十余年,部分领域完全具有核心技术,产业化取得积极进展,但是与国际主流厂商Intel等仍存在较大差距。国产CPU由于受多方因素制约,单核性能并不高,在2000年左右所有的微处理器厂商都转向了多核微处理器的开发。为提升CPU性能,国产CPU均为多核设计。目前,部分产品虽然在党政军部门及重要的信息系统有所应用,但是由于产业生态还未建立,所应用的场景还比较简单,可用于开发应用的编程语言也较为单一。国产CPU的发展事关我国信息产业的核心竞争力和可持续发展力。为了充分发挥国产CPU的性能,需要通过并行编程来解决。

Go语言设计目标之一就是多核编程,不使用多线程编程模型,通过基于CSP的communication通道并发编程,使得并发编程更加简便。Go语言原生支持广泛应用的X86、X64指令集,而且支持龙芯的MIPS64及飞腾的ARM64指令集。这使得Go语言程序在跨平台移植上天生具有优势。Go语言的其他一些特性使得其在国产CPU平台应用具有非常广泛的前景。

1 Go语言简介

Go语言是2009年11月Google正式宣布推出的一种编程语言。它的并发机制使得编写能够充分利用多核和网络通信的程序变得非常容易。Go语言是静态类型的语言,它的类型系统没有层级,完全垃圾回收,比典型的面向对象语言更轻量级;Go语言是一种编译型语言,它结合了解释型语言的游刃有余,动态类型语言的开发效率,以及静态类型的安全性。

Go编译器支持包括:x86、x64、ARM、arm64、ppc64、ppc64le、mips、mipsle、mips64、mips64le、s390x多种不同的CPU指令集。可以支持包括FreeBSD、Linux、Solaris和Windows等的多种操作系统。Go语言是跨平台、跨操作系统的语言,部署非常简单。Go 编译生成的是一个静态可执行文件,除了glibc外没有其他外部依赖。Go的并发性好,而且goroutine 和 channel 使得编写高并发的服务端软件变得相当容易,非常适合用来服务器编程。目前Go语言已经成功的项目包括目前比较流行的云框架Docker、NSQ等分布式框架等。

2 国产CPU平台简介及应用现状

目前,我国自主研发的处理器芯片主要包括龙芯(MIPS64指令集)、申威(Alpha指令集)、飞腾(ARM64指令集)及兆芯(X86指令集)4类。商用领域基于龙芯3B1500 CPU、飞腾FA1500A CPU生产的商用服务器占据国产服务器主流位置,龙芯、飞腾服务器分别搭载中标麒麟及银河麒麟操作系统。

在商用领域,全国产化平台刚刚起步,配套的商用软件较少,没有建立起完整的产业生态,同时又受到处理器自身性能的影响,基于上述两款主流处理器平台的服务器,主要还是用于对系统访问并发及响应时间要求不高的Web网站类网络应用服务。国产处理器应用服务的开发还是以Java语言为主,搭配开源JBoss、Ttomcat或国产中间件,数据库采用国产数据库或MySQL等开源数据库。

3 Go语言在国产平台的优势

3.1 国产平台现有的编程语言匮乏

目前,基于国产CPU的国产化平台比较成熟的仅有C、C++编译器。厂商对Java虚拟机在国产平台上进行编译、适配及优化。由于Java应用运行过程中依赖的大量Java第三方框架都是源于X86构架体系,并未针对国产CPU进行优化,一些应用在大压力或大并发等某些场景下会出现假死、宕机等情况,严重影响应用的正常运行。虽然国产平台也支持其他编程语言如Python、PHP等,但这类脚本语言的解释器也是交叉编译获得的,并非自身支持,在进行跨平台交叉编译过程中会遇到各种问题,很多问题需要软件开发人员修改软件源代码,未经过大量适配验证,很难保证其开发的应用的稳定性。

3.2 Go语言的跨平台及并发优势

Go语言原生支持龙芯CPU的MIPS64le指令集和飞腾CPU的ARM64指令集,天生具有跨平台优势。Go开发应用在任意平台开发完成后,直接编译,编译后的二进制文件在同类平台可直接拷贝运行,无需再次重新编译。除了glibc外,无需其他外部依赖。可以直接在该开发平台的任意计算机上运行,无需像Java运行那样需要虚拟机,需要配置复杂的环境变量;在作为网络服务时更不需要像Tomcat、Apache等的Web中间件。

Go语言的异构平台移植也非常简单,仅需要应用程序的源码,在异构平台上直接编译即可,且编译后的二进制文件在同类平台可直接拷贝运行。Go语言本身就具有天生的跨平台优势,大大降低了分布式异构计算平台的开发难度,非常适合在目前多构架的国产化平台上作为开发语言。

Go语言在并发方面,goroutine和channel机制提供了轻量级并发机制;在性能方面,与Java的性能不分上下,而内存资源消耗方面,相对Java和其他动态语言,具备明显的优势。在网络和HTTP应用方面,Go语言有良好的标准库和生态系统支持,而在标准库方面,已提供了处理多种网络所需的轻量级的代码库,对网络的核心协议HTTP的高并发支持,完全可以撼动Java。国产处理器由于指令集及工艺等多方面原因,导致单核计算性能不高,为提高整体计算能力均采用多核技术。如:龙芯3B1500为8核,商用服务器为双路16核(2颗3B1500),飞腾FT1500A服务器为16核。因此,充分利用多核计算能力或搭建基于国产处理器的云计算平台是目前国产化平台的提高整体性能发展的方向。

4 Go语言在国产环境下的移植

以飞腾平台为例,飞腾CPU采用ARM64构架。首先在X86平台上交叉编译出面向ARM64平台的Go语言自举编译工具,利用$GOOS=linux GOARCH=arm64./bootstrap.bash 编译命令编译出可在ARM64平台运行的Go语言自举编译工具,然后利用该自举编译工具在ARM64平台编译安装Go源码。安装完成后,Go语言会自动进行自身测试。测试完成后提示ALL TESTS PASSED,添加GOROOT至系统环境变量。Go语言的移植完成。龙芯平台移植过程与飞腾平台移植过程不同之处是在编译自举工具时GOARCH参数设置为MIPS64le。

5 Go语言的多核工作原理简介

Go语言可以快速高效地调用多核进行计算,其优势源于Go语言的Go runtime的调度器[2]。

用户空间线程和内核空间线程之间的映射关系有N:1、1:1和M:N 3种通常的线程模型。其中N:1模型是几个用户空间线程在一个OS线程上运行。该模型上下文切换非常快速,但不能利用多核系统的优点。1:1模型一个执行线程匹配一个OS线程。 它利用机器上的所有内核,但上下文切换速度较慢,因为它必须通过操作系统进行。

Go通过使用M:N调度程序来取得上述两种方式的最佳效果。它将任意数量的goroutine调度到任意数量的OS线程上。开发者可以获得快速上下文切换,并利用系统中的所有内核。这种方法的主要缺点是增加了调度器的复杂性。

为了完成调度任务,Go Scheduler使用3个主要实体,如图1所示。

M三角形表示OS线程。这是由操作系统管理的执行线程,其工作原理与标准POSIX线程相似。

G圆圈代表一个goroutine。它包括堆栈、指令指针和其他重要的调度goroutines的信息,像任何可能被阻止的channel等。

P是从N:1调度程序进入M:N调度程序的重要部分,表示调度的上下文。可以将其视为在单个线程上运行Go代码的调度程序,一个局部的调度器。

如图2所示,有2个线程(M),每个线程都有一个上下文(P),每个线程都运行一个goroutine(G)。为了运行goroutines,线程必须持有一个上下文。

P的数量可以通过GOMAXPROCS()来设置,代表了真正的并发度,即有多少个goroutine可以同时运行。可以使用它来调整Go进程到计算机的调用,例如在4核心PC上运行4个线程的Go代码。

白色的goroutines没有运行,处于就绪状态,正在等待被调度。P维护着这个队列。在Go语言里,每当goroutine执行go语句时,goroutines都会添加到队列的末尾。一旦上下文运行了一个goroutine直到调度点,它会从其运行队列中弹出一个goroutine,设置堆栈和指令指针,并开始运行goroutine。

图3中当一个OS线程被阻塞时,P可以转而投奔另一个系统线程。从图中看到,当一个线程M0陷入阻塞时,P转而在OS线程M1上运行。调度器保证有足够的线程来运行所有P。

M1可能是被创建,或者从线程缓存中取出。当syscall返回时,它必须尝试获取一个上下文来运行返回的goroutine,一般情况下,它会从其他的系统线程取得一个上下文,如果没有获取到,它就把goroutine放在一个全局队列中,放入线程缓存里。上下文会周期性地检查全局队列,否则全局队列上的goroutine永远无法执行。

如果上下文的运行队列的工作量不平衡,如图4所示,则可能会发生这种情况。P所分配的任务G很快就执行完了(分配不均),这就导致了一个上下文P空闲而系统忙碌。当一个上下文用完时,它将尝试从另一个上下文中窃取大约一半的运行队列。这确保在每个上下文上总是有工作要做,这反过来确保所有线程都以最大容量工作,每个系统线程都能充分地使用。

6 实测Go语言在国产平台的多核调用

6.1 并行积分计算原理

并行计算积分。计算积分是一个用来展示并发编程和它本身加速度(表示的是多处理器执行时间和单处理器执行时间的比值)的常见例子,例如一个函数f(x)在[a,b]上的积分:

通过循环触发goroutine(协程)来实现np个子算组的并行运算,通过Go代码来计算Pi的积分:

6.2 Go语言并行计算核心代码实现

核心代码:

上述计算中,一个计算组是通过 block(start,end int,c chan float64)这个函数实现的,这个函数计算从start到end之间的矩形面积、通道(channl)c则是用来在结束的时候进行同步,并且把计算组的结果送到主线程。主线程通过调用rutime.GOMAXPROCS(np)建立运行时所使用的CPU核数,np为使用CPU的个数,然后通过make构造一个有np大小缓存的通道,进行阻塞,确保计算并行进行。最后把执行np次的结果进行累加以获得pi的结果。

6.3 Go语言并行计算在国产CPU多核调用测试

6.3.1 测试环境

飞腾平台:FT1500A16核×1;内存16 GB;Go编译器1.8.1;操作系统:银河麒麟4.0。

龙芯平台:3B1500A8核×2;内存16 GB;Go编译器1.8.1;操作系统:中标麒麟6.0。

6.3.2 测试方法

程序内计时,每次测试3次,取最短时间。结果如图5、图6所示。

上面两组数据图展示了,在龙芯3B1500处理器和飞腾FT1500A上,并行Go计算Pi的效率,对于小的问题规模(n=105,106),使用多核不能增加的执行时间,这是因为过多的进程调度和初始化协程导致的,大部分时间没有执行并行计算。当问题规模n变大的时候(n=108,109,1010),使用多处理器能够显著地缩短计算所需的执行时间。

6.3.3 结果对比

结果对比如图7所示。

从图7可以看出,与其他公开的测试的数据基本一致,飞腾FT1500A无论单核和多核性能均比龙芯3B1500CPU计算能力快出近一倍。

6.4 Go语言在调用多核进行并行计算的性能线性特性

为了能够体现并发执行的加速度,以飞腾F1500A为例子以通过式(6)计算速度:

在这里Tnp和TMaxnp是处理器当前使用核数计算所用时间和处理器最大核数计算所用时间。结果如图8所示。

在图8中,当问题规模非常大的时候,增长几乎就是线性的了,特别是问题规模达到(n=109)的时候,几乎和拟合趋势线重合。

7 结束语

本文对Go语言在多线程领域编程、跨异构平台及编程难易程度的优势进行了阐述;对目前我国国产CPU在商业化应用领域现状进行了分析。使用Go语言在主流两款国产平台对多核调用进行测试。同时,对Go语言的多核工作原理进行了简要分析。综上所述,Go语言非常适合作为除Java外的另一种国产CPU平台应用开发语言,有较为广泛的应用前景。本文对未来Go语言在国产CPU平台上的开发及应用提供了一定的参考价值。

参考文献

[1] 芮雪,王亮亮,杨琴.国产处理器研究与发展现状综述[J].现代计算机(普及版),.2014(3):15-19.

[2] MORSING D.The Go scheduler[Z].2013.

作者信息:

陈  希,胡  彬

(国家工业信息安全发展研究中心,北京100040)

 

(0)

相关推荐

  • Videocardz曝光Ryzen Threadripper 1920:12核24线程

    在昨天外媒Videocardz曝光了数款Ryzen Threadripper,其中一款正式名称为Ryzen Threadripper 1920,这是一款12核24线程的CPU,基础频率3200MHz, ...

  • 30 张图讲解:Golang调度器GMP原理与调度全分析

    本文作者:刘丹冰Aceld 公众号同名 该文章主要详细具体的介绍Goroutine调度器过程及原理,可以对Go调度器的详细调度过程有一个清晰的理解,花费4天时间作了30+张图(推荐收藏),包括如下几个 ...

  • 并发与并行的区别是什么?

    让我们先来学习一下抽象程度较高的概念:什么是操作系统的线程(thread)和进程(process).这会有助于后面理解Go语言运行时调度器如何利用操作系统来并发运行goroutine.当运行一个应用程 ...

  • 多核大战一触即发,Intel宣布8月21日发布第八代酷睿处理器

    本文经超能网授权转载,其它媒体转载请经超能网同意. 今年随着AMD携"ZEN"架构的锐龙处理器重返高端CPU市场,整个CPU生态变得十分微妙,你从来没见过一年之内出现了那么多平台的 ...

  • 【golang详解】go语言GMP(GPM)原理和调度

    GMP Goroutine调度是一个很复杂的机制,下面尝试用简单的语言描述一下Goroutine调度机制,想要对其有更深入的了解可以去研读一下源码. 目录 GMP 复用线程 并行 抢占 全局gorou ...

  • Go 为什么这么“快”

    本文主要介绍了 Go 程序为了实现极高的并发性能,其内部调度器的实现架构(G-P-M 模型),以及为了最大限度利用计算资源,Go 调度器是如何处理线程阻塞的场景. 怎么让我们的系统更快 随着信息技术的 ...

  • 再谈协程

    如果你对以下几个问题有疑问,那么本文可能会有所帮助. 什么是协程,或者说为什么会有协程这个概念? 怎么用?什么时候需要用? 都有并行的意味,那么协程和多线程有什么区别?两者能否相互替代? 协程底层的实 ...

  • AMD正在准备三款线程撕裂者的芯片组,HEDT平台有8通道内存用了

    虽然稍早之前AMD从今年的产品线路图中去掉了第三代锐龙线程撕裂者,但是这款产品确实是存在的,AMD本月月初发布第二代EPYC处理器后,估计离HEDT平台的更新也不远了,根据以往的惯例,第三代锐龙线程撕 ...

  • 深入分析 Java、Kotlin、Go 的线程和协程

    前言 协程是什么 协程的好处 进程 进程是什么 进程组成 进程特征 线程 线程是什么 线程组成 任务调度 进程与线程的区别 线程的实现模型 一对一模型 多对一模型 多对多模型 线程的"并发& ...

  • 【学术论文】新型多通道通用信号处理平台设计

    摘要: 介绍基于FPGA分区加载的新型多通道通用信号处理系统,采用FPGA+DSP+ADC架构,支持3通道数十种波形的运行.存储.动态重构功能.该系统适用于机载综合化前端高速射频采样和信号处理小型化应 ...

  • 【学术论文】用于SAR ADC的片上多模式基准电压产生电路的设计

    摘要: 针对工业物联网等应用场景中ADC的供电电压范围宽.功耗要求苛刻等问题,提出了一种配置灵活.低功耗.低噪声的片上基准电压产生电路,为ADC提供与电源无关满量程电压.该电路在电源电压为2.65 V ...

  • 【学术论文】公共元数据配置管理平台设计

       摘 要 : 随着互联网快速发展,各平台利用元数据来组织和管理平台数据资源,平台内平台具有封闭性使得元数据资源分散.反复存储,增大元数据共享难度,降低元数据利用率.为解决这一问题,提出公共元数据配 ...

  • 【学术论文】嵌入式平台下的车辆跟踪系统设计

    摘要: 设计并实现了NVIDIA嵌入式平台Jetson TX2上的车辆跟踪系统.从摄像头采集YUV420格式的视频数据,然后将数据送到Tegra Parker硬件HEVC编码器进行编码,输出码流经过R ...

  • ​【学术论文】星载固态存储控制器标准化通用仿真测试平台设计

    摘要: 电子系统功能与复杂度的日益增加,对系统验证测试的效率提出了更高要求.传统卫星测试平台依据特定型号任务进行定制式设计,其设计开发周期长.综合成本高,难以适应当前任务需求.为此,提出了一种基于Sy ...

  • 【学术论文】主动噪声控制平台的FPGA实现

    摘要: 基于FPGA搭建了针对汽车的主动噪声控制平台,此平台可以正确实时地采集汽车的转速.振动加速度以及噪声,同时为相关的降噪算法实现提供了硬件平台.与传统的基于串行处理的采集系统相比,该平台可以严格 ...

  • 【学术论文】基于Android平台改进的室内WiFi定位算法的研究

    摘要: 基于Android手机平台设计并实现了WiFi室内定位系统.该系统采用指纹定位算法,通过手机采集室内WiFi信息并建立数据库,当用户发出定位请求时,手机将扫描到的WiFi信息发送给数据库,通过 ...

  • 【学术论文】KW01-ZigBee无线传感网应用开发平台的研制

    摘要: 为解决无线传感网应用开发难度大.周期长等问题,通过深入分析其产生原因和无线传感网应用开发技术的现状,按照软件工程思想和构件设计的基本理论,提出了四层架构的开发平台模型.据此研制了一种架构清晰. ...

  • 【学术论文】麒麟操作系统平台软时统同步方法研究

    摘要: 目前测控计算机系统国产化步伐逐步加快,麒麟操作系统平台下软件时统的探索仍处于起步阶段.提出了一种时统软件化的设计方案,并进行了相关技术指标的测试验证,结果表明,软件时统性能指标符合技术要求,为 ...