加入收藏 | 设为首页 | 会员中心 | 我要投稿 莆田站长网 (https://www.0594zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 动态 > 正文

中低频或成5G信号铺设生力军

发布时间:2021-01-31 16:27:55 所属栏目:动态 来源:互联网
导读:毋庸置疑的是,今年以来我国5G建设迎来高速发展阶段。截至目前,三大运营商2020年5G基站建设规划均超前完成,同时,业内还预计,年底5G基站将达到80~90万个。 加速5G应用落地是发展关键 如果说To C是5G发展的起点和基础,那么To B则是价值承载。这点尤其体现

毋庸置疑的是,今年以来我国5G建设迎来高速发展阶段。截至目前,三大运营商2020年5G基站建设规划均超前完成,同时,业内还预计,年底5G基站将达到80~90万个。

加速5G应用落地是发展关键

如果说To C是5G发展的起点和基础,那么To B则是价值承载。这点尤其体现在疫情期间,5G在远程医疗、公共监控、智慧教育、远程办公、巡检物流等领域均发挥了重要作用。

例如:5G远程会诊数十家医院上线使用,实现全方位无障碍移动会诊;5G热成像监测在多省交通枢纽地区普及;5G网络助力火神山、雷神山医院的信息通信畅通,并实现实时直播。另外,5G在线教育、在线协同办公等方面也得到了广泛应用,截至5月11日,国家中小学网络云平台浏览次数达20.73亿,访问人次达17.11亿。

不过,在设备供应商华为看来,5G的发展不能“单打独斗”,需要技术与生态的协同,以及与行业方案提供商、上下游伙伴、客户共同进行创新实践,才能“共创新价值”。

华为公司高级副总裁、中国区总裁鲁勇在实践中发现,不论是远程操控、图像识别,还是无人机器类等场景应用,依靠单纯的5G联接能力是无法实现的,5G只有与智能终端、行业终端、云计算、AI等其他能力协同,并且结合行业信息化系统,才能产生聚变效应,而5G的价值,也才能得以实现。

“在山东、山西的矿区,基于5G实现的远程操控,使得很多工人不必再下井进行几百米深的地下作业。未来‘三高’(高风险、高重复、高精度)类的工作,将随着信息化基础设施的完善和创新,更多由机器来完成。”鲁勇此前在接受包括记者在内的媒体采访时说道。
 

原子性

runtime 使用runtime/internal/atomic中自有的一些原子操作。这个和sync/atomic是对应的,除了方法名由于历史原因有一些区别,并且有一些额外的 runtime 需要的方法。

总的来说,我们对于 runtime 中 atomic 的使用非常谨慎,并且尽可能避免不需要的原子操作。如果对于一个变量的访问已经被另一种同步机制所保护,那么这个已经被保护的访问一般就不需要是原子的。这么做主要有以下原因:

  • 合理地使用非原子和原子操作使得代码更加清晰可读,对于一个变量的原子操作意味着在另一处可能会有并发的对于这个变量的操作。
  • 非原子的操作允许自动的竞争检测。runtime 本身目前并没有一个竞争检测器,但是未来可能会有。原子操作会使得竞争检测器忽视掉这个检测,但是非原子的操作可以通过竞争检测器来验证你的假设(是否会发生竞争)。
  • 非原子的操作可以提高性能。

当然,所有对于一个共享变量的非原子的操作都应当在文档中注明该操作是如何被保护的。

有一些比较普遍的将原子操作和非原子操作混合在一起的场景有:

  • 大部分操作都是读,且写操作被锁保护的变量。在锁保护的范围内,读操作没必要是原子的,但是写操作必须是原子的。在锁保护的范围外,读操作必须是原子的。
  • 仅仅在 STW 期间发生的读操作,且 STW 期间不会有写操作。那么这个时候,读操作不需要是原子的。

话虽如此,Go Memory Model给出的建议仍然成立Don't be [too] clever。runtime 的性能固然重要,但是鲁棒性(robustness)却更加重要。

堆外内存(Unmanaged memory)

一般情况下,runtime 会尝试使用普通的方法来申请内存(堆上内存,gc 管理的),然而在某些情况 runtime 必须申请一些不被 gc 所管理的堆外内存(unmanaged memory)。这是很必要的,因为有可能该片内存就是内存管理器自身,或者说调用者没有一个P(译者注:比如在调度器初始化之前,是不存在P的)。

有三种方式可以申请堆外内存:

  • sysAlloc直接从操作系统获取内存,申请的内存必须是系统页表长度的整数倍。可以通过sysFree来释放。
  • persistentalloc将多个小的内存申请合并在一起为一个大的sysAlloc以避免内存碎片(fragmentation)。然而,顾名思义,通过persistentalloc申请的内存是无法被释放的。
  • fixalloc是一个SLAB风格的内存分配器,分配固定大小的内存。通过fixalloc分配的对象可以被释放,但是内存仅可以被相同的fixalloc池所重用。所以fixalloc适合用于相同类型的对象。

普遍来说,使用以上三种方法分配内存的类型都应该被标记为//go:notinheap(见后文)。

在堆外内存所分配的对象不应该包含堆上的指针对象,除非同时遵守了以下的规则:

  1. 所有在堆外内存指向堆上的指针都必须是垃圾回收的根(garbage collection roots)。也就是说,所有指针必须可以通过一个全局变量所访问到,或者显式地使用runtime.markroot来标记。
  2. 如果内存被重用了,堆上的指针在被标记为 GC 根并且对 GC 可见前必须 以 0 初始化(zero-initialized,见后文)。不然的话,GC 可能会观察到过期的(stale)堆指针。可以参见下文Zero-initialization versus zeroing.

Zero-initialization versus zeroing

在 runtime 中有两种类型的零初始化,取决于内存是否已经初始化为了一个类型安全的状态。

如果内存不在一个类型安全的状态,意思是可能由于刚被分配,并且第一次初始化使用,会含有一些垃圾值(译者注:这个概念在日常的 Go 代码中是遇不到的,如果学过 C 语言的同学应该能理解什么意思),那么这片内存必须使用memclrNoHeapPointers进行zero-initialized或者无指针的写。这不会触发写屏障(译者注:写屏障是 GC 中的一个概念)。

内存可以通过typedmemclr或者memclrHasPointers来写入零值,设置为类型安全的状态。这会触发写屏障。

Runtime-only 编译指令(compiler directives)

除了go doc compile中注明的//go:编译指令外,编译器在 runtime 包中支持了额外的一些指令。

go:systemstack

go:systemstack表明一个函数必须在系统栈上运行,这个会通过一个特殊的函数前引(prologue)动态地验证。

go:nowritebarrier

go:nowritebarrier告知编译器如果以下函数包含了写屏障,触发一个错误(这不会阻止写屏障的生成,只是单纯一个假设)。

一般情况下你应该使用go:nowritebarrierrec。go:nowritebarrier当且仅当“最好不要”写屏障,但是非正确性必须的情况下使用。

go:nowritebarrierrec 与 go:yeswritebarrierrec

go:nowritebarrierrec告知编译器如果以下函数以及它调用的函数(递归下去),直到一个go:yeswritebarrierrec为止,包含了一个写屏障的话,触发一个错误。

逻辑上,编译器会在生成的调用图上从每个go:nowritebarrierrec函数出发,直到遇到了go:yeswritebarrierrec的函数(或者结束)为止。如果其中遇到一个函数包含写屏障,那么就会产生一个错误。

go:nowritebarrierrec主要用来实现写屏障自身,用来避免死循环。

这两种编译指令都在调度器中所使用。写屏障需要一个活跃的P(getg().m.p != nil),然而调度器相关代码有可能在没有一个活跃的P的情况下运行。在这种情况下,go:nowritebarrierrec会用在一些释放P或者没有P的函数上运行,go:yeswritebarrierrec会用在重新获取到了P的代码上。因为这些都是函数级别的注释,所以释放P和获取P的代码必须被拆分成两个函数。

(编辑:莆田站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读