微软指责谷歌“推迟”了surface duo Android 11的升级期限

IT之家 12 月 30 日消息,据 onMSFT 报道,微软看起来越来越有可能错过他们自定的最后期限,即在 2021 年底前为 Surface Duo 初代提供 Android 11 系统更新。当三星已经在向同一年份的手机推送 Android 12 系统时,这一点尤其令人痛心。

然而,根据 Zac Bowden 和 Daniel Rubino 在 Windows Central 播客中的说法,微软并不应该受到责备。

Surface Duo 初代的用户可能最终会在 2022 年 1 月里享受到升级待遇。Windows Central 称,最近微软内部正在 Surface Duo 设备上测试 Android 11 系统。

Android 11 的构建版本已经由微软员工在内部 Surface Duo 设备上自我托管了一段时间。此外,Bowden 透露,他认为最终版本也被传递给了谷歌,但由于谷歌自己的政策,它在进入消费者设备之前必须经过验证。圣诞假期以及谷歌和微软都在休假的事实也意味着验证会有延迟,这就是为什么会有一个漫长的等待。

尽管微软承诺为 Surface Duo 提供为期 3 年的系统更新,但 Android 11 的发布一直是微软粉丝的不安之源。IT之家获悉,Surface Duo 搭载的是 Android 10 系统,微软曾在今年 9 月表示,最初的双屏设备将在 2021 年底前获得 Android 11 系统的更新。

然而,这个时间现在已经过去了,就像该公司之前暗示的最初的夏季时间框架一样。不过,微软确实通过最近的启动器更新将 Android 11 的一些视觉设计元素带到了原来的 Surface Duo 上,这给了社区一些额外的希望。

谷歌发布了JetpackGraceAlpha版本,使得构建Android 12小部件变得更加容易

IT之家 12 月 28 日消息,据谷歌开发者发布,Android 12 改进了一项被许多 Android 用户视为关键的功能 – App Widgets,改进后的 Widgets 更加实用、美观,且更易于被用户发现 (84% 的用户至少使用一个 Widgets)。现在,我们发布了 Jetpack Glance 的第一个 Alpha 版,让 Widgets 的构建过程变得更加轻松,该版本是建立在 Jetpack Compose 运行时 (Runtime) 之上的新框架,旨在实现更快、更轻松的为主屏幕或其他界面构建 App Widgets。

Android 12 Widgets 改进

https://developer.android.google.cn/about/versions/12/features/widgets

App Widgets

https://developer.android.google.cn/guide/topics/appwidgets/overview

Jetpack Glance

https://developer.android.google.cn/jetpack/androidx/releases/glance

Jetpack Compose 运行时 (Runtime)

https://developer.android.google.cn/jetpack/androidx/releases/compose-runtime

欢迎您开始尝试并分享反馈意见:

https://issuetracker.google.com/issues/new?component=1097239&template=1611667

Glance 提供了新式声明性 Kotlin API,其类似于您在 Jetpack Compose 中使用的 API,能够帮助您用更少的代码构建更美观的自适应 App Widgets。

https://developer.android.google.cn/jetpack/compose

△ Glance "Hello World" Widgets 示例

classGreetingsWidget(privatevalname:String):GlanceAppWidget(){
@Composable
overridefunContent(){
Text(text="Hello$name")
}
}
classGreetingsWidgetReceiver:GlanceAppWidgetReceiver(){
overridevalglanceAppWidget=GreetingsWidget("Glance")
}

工作原理

Glance 提供了可组合项的基础组件集,助您打造 "一目了然" 的体验。现在,我们将提供更多的 App Widgets。Glance 利用 Jetpack Compose 运行时 (Runtime),可以将可组合项转化为实际的 RemoteViews,并在 App Widgets 中显示。

△ Glance 结构示意图

可组合项

https://developer.android.google.cn/reference/kotlin/androidx/compose/runtime/Composable

RemoteViews

https://developer.android.google.cn/reference/android/widget/RemoteViews

这意味着 Glance 需要启用 Compose,且依赖于运行时 (Runtime)、图形 (Graphics) 和单元界面 Compose 层,但它与其他现有的 Jetpack Compose 界面元素之间不具备直接互操作性。但是,您可以分享应用中的状态或任何其他逻辑,以此来打造一目了然的界面。

启用 Compose

https://developer.android.google.cn/jetpack/compose/interop/adding#anchor

Compose 层

https://developer.android.google.cn/jetpack/compose/layering

Alpha 版介绍

此初始版本引入了主要的 API,不仅能够实现与现有 RemoteViews 之间的互操作性,还能帮助您构建 App Widgets。

以下是该开发库提供的内容概览:

通过 GlanceAppWidget 和 GlanceAppWidgetReceiver 声明您的 App Widgets。

GlanceAppWidget

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/GlanceAppWidget

GlanceAppWidgetReceiver

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver

利用 Glance 可组合项的初始集组合您的界面: Box、Row、Column、Text、Button、LazyColumn、Image、Spacer。

Box、Row、Column、Spacer

https://developer.android.google.cn/reference/kotlin/androidx/glance/layout/package-summary#top-level-functions

Text

https://developer.android.google.cn/reference/kotlin/androidx/glance/text/package-summary#text

Button

https://developer.android.google.cn/reference/kotlin/androidx/glance/package-summary#button

LazyColumn

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/lazy/package-summary#lazycolumn

Image

https://developer.android.google.cn/reference/kotlin/androidx/glance/package-summary#image

利用 GlanceModifier 方法将修饰符应用于可组合项:

https://developer.android.google.cn/reference/kotlin/androidx/glance/GlanceModifier.html

利用预定义的 Action 处理用户交互:

https://developer.android.google.cn/reference/kotlin/androidx/glance/action/package-summary

actionStartActivity

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/action/package-summary#actionstartactivity

actionRuncallback

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/action/package-summary#actionruncallback

actionStartService

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/action/package-summary#actionstartservice

actionStartBroadcastReceiver

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/action/package-summary#actionstartbroadcastreceiver

通过 ActionParameters 为 Action 提供参数:

https://developer.android.google.cn/reference/kotlin/androidx/glance/action/ActionParameters

通过定义 SizeMode.Single、SizeMode.Exact 或 SizeMode.Responsive 来处理不同的 Widgets 布局。

SizeMode.Single

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/SizeMode.Single

SizeMode.Exact

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/SizeMode.Exact

SizeMode.Responsive

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/SizeMode.Responsive

不同的 Widgets 布局

https://developer.android.google.cn/guide/topics/appwidgets/layouts

提供 GlanceStateDefinition,以保留 GlanceAppWidget 状态。

GlanceStateDefinition

https://developer.android.google.cn/reference/kotlin/androidx/glance/state/GlanceStateDefinition.html

GlanceAppWidget

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/state/package-summary

提供本地组合,例如 LocalContext、LocalState、LocalGlanceId、LocalSize:

https://developer.android.google.cn/reference/kotlin/androidx/glance/package-summary#top-level-properties

通过 AndroidRemoteViews 可组合项实现与您现有 RemoteViews 之间的互操作。

AndroidRemoteViews

https://developer.android.google.cn/reference/kotlin/androidx/glance/appwidget/package-summary#androidremoteviews

RemoteViews

https://developer.android.google.cn/reference/android/widget/RemoteViews.html

我们还将推出更多功能,例如默认主题,更完善的 Android Studio 支持等等。敬请期待新版本:

https://developer.android.google.cn/jetpack/androidx/releases/glance

注意: 虽然 SDK 的最低版本是 21,但 Alpha 版目前支持兼容的最低版本为 SDK v23。

△ 在 Android 12 中构建新式 Android App Widgets

Glance 使用入门

您可以在 GitHub 上查看示例,以便快速入门。也可以在最新的稳定版 Android Studio 中使用 Glance,但首先需要按照 Jetpack Compose 文档中的步骤进行设置,因为 Glance 依赖于 Compose 运行时 (Runtime)。

示例

https://github.com/android/user-interface-samples/tree/glance/AppWidget/glance-widget

稳定版 Android Studio

https://developer.android.google.cn/studio

Jetpack Compose 文档

https://developer.android.google.cn/jetpack/compose/interop/adding#setup

此外,您还可以查看 AndroidX 代码库中的进阶示例:

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/

编写您自己的插件,您可以扩展 Android Gradle Plugin 并根据您的项目需求自定义您的构建!

△ ResponsiveAppWidget.kt 演示

ResponsiveAppWidget.kt

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:glance/glance-appwidget/integration-tests/demos/src/main/java/androidx/glance/appwidget/demos/ResponsiveAppWidget.kt

从10000人的关注到令人沮丧的退出,谷歌眼镜在5g普及之前就已经消亡了

在2019年谷歌眼镜最后一次更新中,删除了谷歌眼镜与服务器端的链接功能与设备上的谷歌账户,谷歌眼镜上的Gmail和YouTube也会随之消失。也就是说谷歌眼镜将失去谷歌框架的支持,也将无法再链接其他谷歌应用和网络——谷歌眼镜这款曾经被谷歌寄予厚望的产品,最终倒在了本有可能大放光彩的5G之前。

跳伞登场的谷歌眼镜

将时间拨回2012年的谷歌I/O开发者大会的最后阶段,传说已久的谷歌眼镜突然亮相——

创始人谢尔盖·布林率着一队跳伞运动员从一艘策帕林飞艇上一跃而下,用让人尖叫的跳伞方式将谷歌眼镜带到了世人眼前。

谷歌眼镜可以解放双手

谷歌眼镜不止是外表酷炫,更为重要的则是它带来"解放双手"的可能,想象一下所有信息都在眼前显示,你不用再从兜里掏出手机;你也可以完成诸如边骑车边收发短信等以往做不到的事情。谷歌眼镜可以在理论上代替手机的大部分功能,同时还能做到手机做不到的事情——比如一边做饭一边查菜谱,更为重要的则是还很帅——这都让这款可穿戴设备充满了想象力。

但这么多年过去了,iWatch都已经出到了5代,各种智能手环也是层出不穷,苹果的Apple AirPods耳机甚至卖出了6000万部,而谷歌眼镜呢?在2015年就停止了销售,而在2019年则关闭了所有服务。是可穿戴设备市场的问题吗?显然不是,苹果和小米华为等厂商已经证明了可穿戴市场的需求。但谷歌眼镜最大的问题可能是它的步子迈的太大了。

iWatch

和手表手环这些附属品属性较强的商品不同,谷歌眼镜占据了人类眼镜这一主要消息输入源。至少在2015年的谷歌眼镜版本还无法有效过滤信息,你无法过滤那些对你来说无用的信息。而且谷歌眼镜上市的时候,相关的应用还很不完善,包括视频会议和语音回复短信仍在开发中,无法使用。而谷歌对于谷歌眼镜的支持也并不坚定,这也影响了后续开发者跟进的热情。更为严重的则是高达1500美元的售价,这已经超过了一般旗舰手机的价格,花费如此高的价格去购买一个生态还没有建立起来的谷歌眼镜无疑是一件不明智的事情。

探索版地谷歌眼镜不够完善,这在谷歌来说也是心知肚明地一件事情。但遗憾的是在2014年4月发布之后,谷歌没有制定下一代谷歌硬件的硬件路线图,这才是最令开发者恐惧的。没有多少开发者原因投入一个随时有可能被放弃的项目之中。而缺乏应用和使用场景又加剧了谷歌对于谷歌眼镜未来的担忧,最终在短短一年后的2015年就宣布停止销售谷歌眼镜,但依然提供服务。

谷歌眼镜实际效果

放弃硬件更新的抉择很糟糕,因为谷歌眼镜还很不完善:耗电量大发热严重,佩戴不方便成像效果不理想,硬件和软件结合很差等等。所以戴上谷歌眼镜的效果不但不酷,反而会显得很奇怪。

谷歌放弃谷歌眼镜的另一个因素可能就是隐私。谷歌一直饱受隐私问题的困扰,也频频因为保护隐私不利而被公众批评,而谷歌眼镜面临的隐私问题则更为严峻,谷歌眼镜的用户被称作"眼镜恶棍(glassholes)",遭到公开羞辱。这更是降低了大家购买谷歌眼镜的欲望。

而在放弃硬件之后,软件服务的支持也将在2020年2月25日之后彻底结束。这款本来前途无量被认为将挑战智能手机的创新产品变成了一个公开的笑话,倒在了本来有机会大放光彩的5G时代之前。

可穿戴设备

智能穿戴设备依然有未来,特别是在5G技术的加持下,大量的智能穿戴设备创业公司又开始蠢蠢欲动。在考虑创业方向的时候不妨再回头看看曾经的创业明星谷歌眼镜是如何失败的,这或许会让创业者学到有用的教训。

IDC:百度超越谷歌,在中国深度学习平台的综合市场份额排名第一

近日,权威数据调研机构IDC发布2021年上半年深度学习框架平台市场份额报告。调研显示,百度在中国深度学习平台市场中的综合份额持续增长,跃居第一。

人工智能正在进入大规模落地阶段,越来越多的开发者和企业基于深度学习平台构建、训练和部署智能应用。通过此次IDC报告可以看到,百度的深度学习平台建设已走在世界前列。百度飞桨、Google、Facebook形成鼎立格局,飞桨继续稳步增长。飞桨企业版EasyDL保持市场排名首位,BML显现强劲增速。作为我国首个自主研发、功能丰富、开源开放的产业级深度学习平台,飞桨通过持续的技术创新突破、产业人才赋能、社区生态共建,获得了市场广泛认可。

(飞桨全景图)

百度飞桨之所以受到中国开发者的欢迎,在于其扎根实际应用场景,牢牢抓住了开发者和企业智能化升级的需求,不断降低人工智能技术的应用门槛。百度首席技术官王海峰指出,人工智能技术具有通用性,呈现标准化、自动化、模块化的特征,进入工业大生产阶段。在新的发展阶段,一方面,人工智能技术越来越复杂,融合创新越来越丰富;另一方面,随着人工智能技术在各行业的渗透,面向不同应用场景,降低门槛非常关键。

作为源于产业实践的深度学习开源开放平台,飞桨一直致力于降低门槛,满足不同行业、不同阶段、不同层次开发者的需求。飞桨具备开发便捷的深度学习框架、超大规模深度学习模型训练技术、多端多平台部署的高性能推理引擎、产业级开源模型库四大领先技术。面向产业AI应用场景,推出企业版双平台开发模式,EasyDL零门槛AI开发平台和BML全功能AI开发平台,帮助企业开发者加速 AI 应用创新落地。

IDC调研中也发现,越来越多的入门级开发者、传统行业的工程师正在学习和使用飞桨。EasyDL继续保持市场第一,BML市场增速强劲。这意味着飞桨在企业级AI服务中成为了市场首选。凭借更低的应用门槛,便捷高效的开发服务,EasyDL和BML赢得了企业开发者青睐。

快速崛起的飞桨推动着中国的产业智能化进程。截至目前,飞桨凝聚了320万开发者,服务12万家企事业单位,覆盖农业、工业、林业、民生、通信、电力、公益、城市管理等数十个行业,创建了36万个模型。同时,飞桨积极助力培养AI人才,通过AICA首席AI架构师培养计划向业界输出190位高端复合型AI人才;面向高校的深度学习师资培训,助力全国超过200所高校开设了AI学分课,惠及数万学生。百度飞桨助力中国的产业智能化走得更快更远。

— 完 —

谷歌推出了自然语言框架语义分析器sling,但没有说明它是否有用

编者按:美国时间周三,谷歌官方博客介绍了科学家Michael Ringgaard和Rahul Gupta的一个实验性自然语言框架语义解析器,称能绕过分词、生成词向量等步骤,利用语义框架直接完成文本解析。这个新工具SLING基于框架语义学,提出了一些令人振奋的思路,但由于缺少干货佐证,我们无法得知它在框架搭建上的具体突破。

谷歌在博文中是这样介绍的:

现如今,大多数实用的自然语义理解(NLU)还在使用逐级解析的方法,从词性标注到生成词向量到生成依存句法分析再到文本分析,虽然这种模块化的方法有利于模型训练,但它也带来一个问题:前期犯的错误会产生级联效应,直接影响后期输出及最终模型的准确率。

为了解决这个问题,谷歌今天推荐的自然语言框架语义解析器SLING提出了一种思路——建立一个基于自然语言文本的语义框架图。输入语句后,该框架能直接捕获用户感兴趣的内容进行标注,原本分级的步骤在这里是平行的,谷歌认为这样能避免“流水线”式的缺陷,防止不需要的计算。据介绍,SLING基于一个专用的循环神经网络(RNN),它直接在框架图上对输入文本进行增量编译。框架图足够灵活,能高效提取开发者感兴趣的语义任务;SLING的解析器只针对单词,因此可以绕过一些中间环节,如生成依存句法分析。

SLING产生的代码在RNN上inference的速度很快,在桌面级CPU上的解析速度可超过2500令牌/秒。这主要依靠以下两个设计:

  • 一种高效的、可扩展的框架存储实现;

  • 一个JIT编译器。

它是用C++实现的,感兴趣的读者可以前往github下载。

框架语义分析

SLING采用的语言学理论是框架语义学,这是认知语言学的一个分支,利用语义框架、语义网络来理解词汇意义,而非语法句法分析。它把句子作为一个语义框架,语义框架中词元的语义类别不同,与之相关的语义角色的名称就不同。

如在以下示例中,例句可以被简单粗暴地划分为三种成分让SLING归类:实体(人物、地点、事件等)、度量(日期、距离等)和其他概念(动词类成分等)——

Many people now claim to have predicted Black Monday

people是人物,Black Monday是事件,predicted是连接人物和事件的行为(其他概念),可单独作为一个框架元素PREDICT-01。当与人物发生相互作用时,PREDICT-01通过ARG0插槽表示“谁做的预测”,当与事件发生相互作用时,则用ARG1插槽表示“预测了什么”。整个判断过程基于语义概念结构,不会细化到针对每一个动词。

虽然这个例子很简单,但依靠现有的框架语义学研究,这种方法在一些涉及参考、隐喻、转喻的复杂句上会有尤其出色的表现。值得一提的是,它适合用语料库做模型的开发者。

SLING

SLING训练RNN的方法是优化语义框架。

正如之前提到的,在SLING里,现行的逐级分析是平行的,所以它不需要手动分词、通过流水线提取特征,它把这些都步骤放进了隐藏层。在神经网络内部,SLING使用了一个编码器—解码器体系结构,它把输入的单词做原始处理,依据词典语义特征编码成一个向量,并附上后缀(ES),解码器也会对标点符号做处理。

这之后,SLING会把它们和各自的历史特征结合起来,逐个分析构成意义的ARG插槽,获得句子的预期语义框架。这一模型已在TensorFlow和DRAGNN中完成训练。

如上图所示,SLING逐个分析单词所能够成的语义框架元素,并根据相互关系生成句子结构,最后一个单词输入完毕后,整个模型会进行一次再调整,把最完整的语义框架反馈给开发者。值得注意的是,一些单词输入后,如果无法立即判断它在框架中的作用,SLING会把它先储存到缓冲区,再由之后的单词诱发判断。在不做句法依存生成的基础上,这种做法对于捕捉框架元素之间的关系异常有效。

自己动手从0实现分布式RPC框架

前言

为什么要自己写一个RPC框架,我觉得从个人成长上说,如果一个程序员能清楚的了解RPC框架所具备的要素,掌握RPC框架中涉及的服务注册发现、负载均衡、序列化协议、RPC通信协议、Socket通信、异步调用、熔断降级等技术,可以全方位的提升基本素质。虽然也有相关源码,但是只看源码容易眼高手低,动手写一个才是自己真正掌握这门技术的最优路径。

一 什么是RPC

RPC(Remote Procedure Call)远程过程调用,简言之就是像调用本地方法一样调用远程服务。目前外界使用较多的有gRPC、Dubbo、Spring Cloud等。相信大家对RPC的概念都已经很熟悉了,这里不做过多介绍。

二 分布式RPC框架要素

一款分布式RPC框架离不开三个基本要素:

  • 服务提供方 Serivce Provider
  • 服务消费方 Servce Consumer
  • 注册中心 Registery

围绕上面三个基本要素可以进一步扩展服务路由、负载均衡、服务熔断降级、序列化协议、通信协议等等。

1 注册中心

主要是用来完成服务注册和发现的工作。虽然服务调用是服务消费方直接发向服务提供方的,但是现在服务都是集群部署,服务的提供者数量也是动态变化的,所以服务的地址也就无法预先确定。因此如何发现这些服务就需要一个统一注册中心来承载。

2 服务提供方(RPC服务端)

其需要对外提供服务接口,它需要在应用启动时连接注册中心,将服务名及其服务元数据发往注册中心。同时需要提供服务服务下线的机制。需要维护服务名和真正服务地址映射。服务端还需要启动Socket服务监听客户端请求。

3 服务消费方(RPC客户端)

客户端需要有从注册中心获取服务的基本能力,它需要在应用启动时,扫描依赖的RPC服务,并为其生成代理调用对象,同时从注册中心拉取服务元数据存入本地缓存,然后发起监听各服务的变动做到及时更新缓存。在发起服务调用时,通过代理调用对象,从本地缓存中获取服务地址列表,然后选择一种负载均衡策略筛选出一个目标地址发起调用。调用时会对请求数据进行序列化,并采用一种约定的通信协议进行socket通信。

三 技术选型

1 注册中心

目前成熟的注册中心有Zookeeper,Nacos,Consul,Eureka,它们的主要比较如下:

本实现中支持了两种注册中心Nacos和Zookeeper,可根据配置进行切换。

2 IO通信框架

本实现采用Netty作为底层通信框架,Netty是一个高性能事件驱动型的非阻塞的IO(NIO)框架。

3 通信协议

TCP通信过程中会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。所以需要对发送的数据包封装到一种通信协议里。

业界的主流协议的解决方案可以归纳如下:

  1. 消息定长,例如每个报文的大小为固定长度100字节,如果不够用空格补足。
  2. 在包尾特殊结束符进行分割。
  3. 将消息分为消息头和消息体,消息头中包含表示消息总长度(或者消息体长度)的字段。

很明显1,2都有些局限性,本实现采用方案3,具体协议设计如下:

+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| BYTE | | | | | | | ........
+--------------------------------------------+--------+-----------------+--------+--------+--------+--------+--------+--------+-----------------+
| magic | version| type | content lenth | content byte[] | |
+--------+-----------------------------------------------------------------------------------------+--------------------------------------------+

  • 第一个字节是魔法数,比如我定义为0X35。
  • 第二个字节代表协议版本号,以便对协议进行扩展,使用不同的协议解析器。
  • 第三个字节是请求类型,如0代表请求1代表响应。
  • 第四个字节表示消息长度,即此四个字节后面此长度的内容是消息content。

4 序列化协议

本实现支持3种序列化协议,JavaSerializer、Protobuf及Hessian可以根据配置灵活选择。建议选用Protobuf,其序列化后码流小性能高,非常适合RPC调用,Google自家的gRPC也是用其作为通信协议。

5 负载均衡

本实现支持两种主要负载均衡策略,随机和轮询,其中他们都支持带权重的随机和轮询,其实也就是四种策略。

四 整体架构

五 实现

项目总体结构:

1 服务注册发现

Zookeeper

Zookeeper采用节点树的数据模型,类似linux文件系统,/,/node1,/node2 比较简单。

Zookeeper节点类型是Zookeeper实现很多功能的核心原理,分为持久节点临时节点、顺序节点三种类型的节点。

我们采用的是对每个服务名创建一个持久节点,服务注册时实际上就是在zookeeper中该持久节点下创建了一个临时节点,该临时节点存储了服务的IP、端口、序列化方式等。

客户端获取服务时通过获取持久节点下的临时节点列表,解析服务地址数据:

客户端监听服务变化:

Nacos

Nacos是阿里开源的微服务管理中间件,用来完成服务之间的注册发现和配置中心,相当于Spring Cloud的Eureka+Config。

不像Zookeeper需要利用提供的创建节点特性来实现注册发现,Nacos专门提供了注册发现功能,所以其使用更加方便简单。主要关注NamingService接口提供的三个方法registerInstance、getAllInstances、subscribe;registerInstance用来完成服务端服务注册,getAllInstances用来完成客户端服务获取,subscribe用来完成客户端服务变动监听,这里就不多做介绍,具体可参照实现源码。

2 服务提供方 Serivce Provider

在自动配置类OrcRpcAutoConfiguration完成注册中心和RPC启动类(RpcBootStarter)的初始化:

服务端的启动流程如下:

RPC启动(RpcBootStarter):

上面监听Spring容器初始化事件时注意,由于Spring包含多个容器,如web容器和核心容器,他们还有父子关系,为了避免重复执行注册,只处理顶层的容器即可。

3 服务消费方 Servce Consumer

服务消费方需要在应用启动完成前为依赖的服务创建好代理对象,这里有很多种方法,常见的有两种:

  • 一是在应用的Spring Context初始化完成事件时触发,扫描所有的Bean,将Bean中带有OrcRpcConsumer注解的field获取到,然后创建field类型的代理对象,创建完成后,将代理对象set给此field。后续就通过该代理对象创建服务端连接,并发起调用。
  • 二是通过Spring的BeanFactoryPostProcessor,其可以对bean的定义BeanDefinition(配置元数据)进行处理;Spring IOC会在容器实例化任何其他bean之前运行BeanFactoryPostProcessor读取BeanDefinition,可以修改这些BeanDefinition,也可以新增一些BeanDefinition。

本实现也采用第二种方式,处理流程如下:

BeanFactoryPostProcessor的主要实现:

@Override
public void postProcessbeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
this.beanFactory = beanFactory;
postProcessRpcConsumerBeanFactory(beanFactory, (BeanDefinitionRegistry)beanFactory);
}

private void postProcessRpcConsumerBeanFactory(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry beanDefinitionRegistry) {
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
int len = beanDefinitionNames.length;
for (int i = 0; i < len; i++) {
String beanDefinitionName = beanDefinitionNames[i];
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null) {
Class<?> clazz = ClassUtils.resolveClassName(beanClassName, classLoader);
ReflectionUtils.doWithFields(clazz, new FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
parseField(field);
}
});
}

}

Iterator<Entry<String, BeanDefinition>> it = beanDefinitions.entrySet().iterator();
while (it.hasNext()) {
Entry<String, BeanDefinition> entry = it.next();
if (context.containsBean(entry.getKey())) {
throw new IllegalArgumentException("Spring context already has a bean named " + entry.getKey());
}
beanDefinitionRegistry.registerBeanDefinition(entry.getKey(), entry.getValue());
log.info("register OrcRpcConsumerBean definition: {}", entry.getKey());
}

}

private void parseField(Field field) {
// 获取所有OrcRpcConsumer注解
OrcRpcConsumer orcRpcConsumer = field.getAnnotation(OrcRpcConsumer.class);
if (orcRpcConsumer != null) {
// 使用field的类型和OrcRpcConsumer注解一起生成BeanDefinition
OrcRpcConsumerBeanDefinitionBuilder beanDefinitionBuilder = new OrcRpcConsumerBeanDefinitionBuilder(field.getType(), orcRpcConsumer);
BeanDefinition beanDefinition = beanDefinitionBuilder.build();
beanDefinitions.put(field.getName(), beanDefinition);
}
}

ProxyFactory的主要实现:

public class JdkProxyFactory implements ProxyFactory{

@Override
public Object getProxy(ServiceMetadata serviceMetadata) {
return Proxy
.newProxyInstance(serviceMetadata.getClazz().getClassLoader(), new Class[] {serviceMetadata.getClazz()},
new ClientInvocationHandler(serviceMetadata));
}

private class ClientInvocationHandler implements InvocationHandler {

private ServiceMetadata serviceMetadata;

public ClientInvocationHandler(ServiceMetadata serviceMetadata) {
this.serviceMetadata = serviceMetadata;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String serviceId = ServiceUtils.getServiceId(serviceMetadata);
// 通过负载均衡器选取一个服务提供方地址
ServiceURL service = InvocationServiceSelector.select(serviceMetadata);

OrcRpcRequest request = new OrcRpcRequest();
request.setMethod(method.getName());
request.setParameterTypes(method.getParameterTypes());
request.setParameters(args);
request.setRequestId(UUID.randomUUID().toString());
request.setServiceId(serviceId);

OrcRpcResponse response = InvocationClientContainer.getInvocationClient(service.getServerNet()).invoke(request, service);
if (response.getStatus() == RpcStatusEnum.SUCCESS) {
return response.getData();
} else if (response.getException() != null) {
throw new OrcRpcException(response.getException().getMessage());
} else {
throw new OrcRpcException(response.getStatus().name());
}
}
}
}

本实现只使用JDK动态代理,也可以使用cglib或Javassist实现以获得更好的性能,JdkProxyFactory中。

4 IO模块

UML图如下:

结构比较清晰,分三大模块:客户端调用适配模块、服务端请求响应适配模块和Netty IO服务模块。

客户端调用适配模块

此模块比较简单,主要是为客户端调用时建立服务端接,并将连接存入缓存,避免后续同服务调用重复建立连接,连接建立成功后发起调用。下面是DefaultInvocationClient的实现:

服务端请求响应适配模块

服务请求响应模块也比较简单,是根据请求中的服务名,从缓存中获取服务元数据,然后从请求中获取调用的方法和参数类型信息,反射获取调用方法信息。然后从spring context中获取bean进行反射调用。

Netty IO服务模块

Netty IO服务模块是核心,稍复杂一些,客户端和服务端主要处理流程如下:

其中,重点是这四个类的实现:NettyNetClient、NettyNetServer、NettyClientChannelRequestHandler和NettyServerChannelRequestHandler,上面的UML图和下面流程图基本上讲清楚了它们的关系和一次请求的处理流程,这里就不再展开了。

下面重点讲一下编码解码器。

在技术选型章节中,提及了采用的通信协议,定义了私有的RPC协议:

+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+
| BYTE | | | | | | | ........
+--------------------------------------------+--------+-----------------+--------+--------+--------+--------+--------+--------+-----------------+
| magic | version| type | content lenth | content byte[] | |
+--------+-----------------------------------------------------------------------------------------+--------------------------------------------+

  • 第一个字节是魔法数定义为0X35。
  • 第二个字节代表协议版本号。
  • 第三个字节是请求类型,0代表请求1代表响应。
  • 第四个字节表示消息长度,即此四个字节后面此长度的内容是消息content。

编码器的实现如下:

@Override
protected void encode(ChannelHandlerContext channelHandlerContext, ProtocolMsg protocolMsg, ByteBuf byteBuf)
throws Exception {
// 写入协议头
byteBuf.writeByte(ProtocolConstant.MAGIC);
// 写入版本
byteBuf.writeByte(ProtocolConstant.DEFAULT_VERSION);
// 写入请求类型
byteBuf.writeByte(protocolMsg.getMsgType());
// 写入消息长度
byteBuf.writeInt(protocolMsg.getContent().length);
// 写入消息内容
byteBuf.writeBytes(protocolMsg.getContent());
}

解码器的实现如下:

六 测试

在本人MacBook Pro 13寸,4核I5,16g内存,使用Nacos注册中心,启动一个服务器,一个客户端情况下,采用轮询负载均衡策略的情况下,使用Apache ab测试。

在启用8个线程发起10000个请求的情况下,可以做到 18秒完成所有请求,qps550:

在启用100个线程发起10000个请求的情况下,可以做到 13.8秒完成所有请求,qps724:

七 总结

在实现这个RPC框架的过程中,我也重新学习了很多知识,比如通信协议、IO框架等。也横向学习了当前最热的gRPC,借此又看了很多相关的源码,收获很大。后续我也会继续维护升级这个框架,比如引入熔断降级等机制,做到持续学习持续进步。

作者 | 麓行

原文链接:https://click.aliyun.com/m/1000282969/

本文为阿里云原创内容,未经允许不得转载。

Google、deepmind、Microsoft和Uber大型培训深度学习模型框架介绍

大规模训练是在现实世界中构建深度学习解决方案最具挑战性的方面之一。。从训练到优化,深度学习程序的生命周期需要健壮的基础设施构建块,以便能够并行化和扩展计算工作负载。尽管深度学习框架正在快速发展,但相应的基础架构模型仍处于初期阶段。在过去的几年中,技术巨头Google,Microsoft,Uber,DeepMind和其他公司定期发布了研究成果,以实现跨大型GPU基础架构的深度学习模型的并行化。

分布式和并行化计算的原理与深度学习程序生命周期的几乎所有阶段都息息相关。训练一个深度学习模型是一项非常昂贵的练习,它的执行也是如此。显而易见的答案是,可以利用大型GPU网络来分配深度学习程序的工作负载,但这绝非易事。众所周知,并发和并行编程是非常复杂的,在应用于大型神经网络时更是如此。今天,我想回顾一下在谷歌、DeepMind、Microsoft和Uber中用于并行化大规模深度学习模型训练的一些顶级架构。

谷歌的GPipe

GPipe专注于为深度学习项目扩展训练工作量。从基础架构的角度来看,训练过程的复杂性是深度学习模型中经常被忽视的一个方面。训练数据集越来越大,越来越复杂。例如,在卫生保健领域,遇到需要使用数百万高分辨率图像进行训练的模型并不罕见。结果,训练过程通常要花很长时间才能完成,由于内存和CPU消耗而导致的成本也非常高。

将深度学习模型的并行性分为数据并行性和模型并行性是研究深度学习模型并行性的有效方法。数据并行方法使用大量的机器集群来拆分输入数据。模型并行性尝试将模型移至具有专用硬件以加速模型训练的加速器,例如GPU或TPU。几乎所有的训练数据集都可以按照一定的逻辑并行化,但模型却不是这样。例如,一些深度学习模型是由可以独立训练的并行分支组成的。在这种情况下,典型的策略是将计算划分为分区,并将不同的分区分配给不同的分支。然而,这种策略在顺序堆叠层的深度学习模型中存在不足,这给高效地并行化计算带来了挑战。

GPipe利用一种称为管道的技术,将数据和模型并行性结合起来。从概念上讲,GPipe是一个分布式机器学习库,它使用同步随机梯度下降和管道并行性进行训练,适用于任何由多个连续层组成的DNN。GPipe将一个模型划分到不同的加速器上,并自动将一个小批量的训练实例分割成更小的微批量。该模型允许GPipe的加速器并行运行,以最大限度地提高训练过程的可伸缩性。

下图说明了神经网络的GPipe模型在四个加速器之间的划分。Fk是第k个划分的复合正向计算函数。Bk是对应的反向传播函数。Bk既依赖于上层的Bk+1,也依赖于Fk的中间激活。在模型上部中,我们可以看到网络的顺序特性是如何导致资源利用不足的。图片下部显示了GPipe方法,其中输入的mini-batch被分成更小的macro-batches,这些macro-batches可以由加速器同时处理。

Uber Horovod

Horovod是在社区中变得极为流行的Uber ML堆栈之一,并已被DeepMind或OpenAI等AI巨头的研究团队采用。从概念上讲,Horovod是用于大规模运行分布式深度学习训练工作的框架。

Horovod利用诸如OpenMPI之类的消息传递接口栈来使训练作业能够在高度并行且分布式的基础架构上运行,而无需进行任何修改。通过以下四个简单的步骤即可在Horovod中运行分布式TensorFlow训练工作:

  1. hvd.init()初始化Horovod。
  2. config.gpu_options.visible_device_list = str(hvd.local_rank())为每个TensorFlow进程分配一个GPU。
  3. opt = hvd.DistributedOptimizer(opt)使用Horovod优化器包装任何常规的TensorFlow优化器,该优化器使用ring-allreduce来平均梯度。
  4. hvd.BroadcastGlobalVariablesHook(0)将变量从第一个进程广播到所有其他进程,以确保一致的初始化。

这是基本TensorFlow训练作业的模板:

DeepMind的TF-Replicator

TF-Replicator专注于与TensorFlow程序如何利用Tensor处理单元(TPU)相关的可伸缩性的不同方面。TPU被认为是最先进的AI芯片之一,可为机器学习工作负载提供本地可扩展性。但是,在TensorFlow程序中使用TPU 需要专用的API,这会给不熟悉底层硬件模型的数据科学家带来可移植性问题和采用障碍。DeepMind的TF复制器通过提供一个更简单,友好的开发程序模型来利用TensorFlow程序中的TPU,从而解决了这一难题。

TF-Replicator关注的是可伸缩性的另一个方面,即TensorFlow程序如何利TPU。TPU被认为是最先进的人工智能芯片之一,它为机器学习工作负载提供了本机可伸缩性。然而,在TensorFlow程序中使用TPU需要专门的api,这会导致可移植性问题。DeepMind的TF-Replicator提供了一个更简单、对开发人员友好的编程模型,用于在TensorFlow程序中利用TPU。

TF-Replicator的魔力在于“in-graph replication”模式,其中每个设备的计算都复制到同一TensorFlow图中。设备之间的通信是通过连接设备相应子图中的节点来实现的。为了达到该级别的并行化,TF-Replicator利用TensorFlow的图重写模型在图中的设备之间插入本地通信。当提供一个TensorFlow图时,TF-Replicator首先独立地构建每个设备的计算,并在用户指定跨设备计算的地方留下占位符。一旦构建了所有设备的子图,TF-Replicator就会用实际的跨设备计算代替占位符来连接它们。

从编程模型的角度来看,使用TF-Replicator编写的代码看起来类似于为单个设备编写的本机TensorFlow代码。用户只需要定义(1)公开数据集的输入函数,(2)定义其模型逻辑的阶跃函数(例如,梯度下降的单个阶跃)。以下Python代码片段显示了一个简单的TF-Replicator程序:

为了优化不同设备之间的通信,TF-Replicator利用了最先进的MPI接口。在一些实验中,DeepMind能够在TPUv3 pod的512个核上,以2048的batches size训练著名的BigGAN模型。目前,TF-Replicator是DeepMind的主要TPU编程接口。

微软DeepSpeed

微软的DeepSpeed是一个新的开源框架,专注于优化大型深度学习模型的训练。当前版本包括ZeRO的第一个实现以及其他优化方法。从编程的角度来看,DeepSpeed是建立在PyTorch之上的,它提供了一个简单的API,让工程师们只需几行代码就可以利用并行化技术进行训练。DeepSpeed抽象了大规模训练的所有困难方面,例如并行化、混合精度、梯度累积和检查点,使开发人员可以专注于模型的构建。

DeepScale在四个关键方面都表现出色:

· 规模: DeepSpeed提供系统支持以运行多达1000亿个参数的模型,与其他训练优化框架相比,这代表了10倍的改进。

· 速度:在最初的测试中,DeepSpeed显示出的吞吐量是其他库的4到5倍。

· 成本:使用DeepSpeed训练模型的成本比其他方法低三倍。

· 可用性: DeepSpeed不需要重构PyTorch模型,仅需几行代码即可使用。

将深度学习模型的训练并行化是一项非常复杂的练习,超出了大多数机器学习团队的专业能力。利用谷歌、微软(Microsoft)、优步(Uber)或DeepMind等科技公司创建的框架和架构,肯定可以简化这些工作。

Android底层原理分析:网络请求框架改造的详细说明

在Android开发过程中,有很多的网络请求框架,比如Volley、Async Http Client,但是我们为什么要用Retrofit呢 ?

一个词:方便。使用方便,修改也方便。

Retrofit的优点

  • 可以配置不同HTTP client来实现网络请求;
  • 请求的方法参数注解都可以定制;
  • 支持同步、异步和RxJava;
  • 超级解耦;
  • 可以配置不同的反序列化工具来解析数据,如json、xml等;
  • 使用非常方便灵活;
  • 支持GET/POST/PUT/DELETE/HEAD/PATCH协议。

总的来说,Retrofit是一个基于OkHttp的高解耦的网络框架。功能强大、简洁易用,基本上也是我们现在天天在用的一个框架。

Retrofit说起来相当简单,简单到源码只有37个文件,其中22个文件是注解,还都和HTTP有关,真正暴露给用户的类并不多。Retrofit其实就是一个网络请求框架的封装,一般常用的框架组合是:RxJava+Retrofit+OkHttp。

但是只有会用是远远不够的,我们还要深入底层,学习原理。每年BAT这些大厂关于Okhttp和Retrofit的题目都能难倒一大批应聘者,这些题目要么开放性很强、要么需要对源码有很深的理解。

比如下面我从牛客网的面经整理出来的题目:

  • 什么是动态代理?和静态代理的区别是什么?JDK中动态代理是怎么实现的?
  • 在项目中你有用到哪些设计模式?解决了什么问题?
  • 怎么使用OkHttp或者Retrofit完成文件下载上传?
  • 如果网络比较差,2G/3G,怎么进行弱网优化?
  • Http1和Http2的区别是什么?
  • 谈谈TCP与UDP的理解
  • okhttp为什么会使用okio而不是用普通io
  • socket连接池怎么复用的
  • tcp怎么拥塞控制?SSL的握手和采用的加密算法
  • okHttp进行网络请求优化的原理?

这些问题都需要我们对okhttp和Retrofit的原理非常熟悉,并且还要能结合自己的思想,说出自己的理解。

网络是项目开发中不可或缺的部分,但是很多程序员平时都是CV编程,以至于面试被问到为什么要使用Retrofit、OkHttp都答不出个所以然来!

今天想和大家分享的是一份由阿里大佬整理出来的 Android 开发相关源码精编解析,这份资料对Retrofit、OkHttp都有完整的解析。

此外,这份资料一共有508页,18大版块,全是Android开发相关源码的精编解析。相信大家在看完这份资料后会对Android源码有更深的理解!

资料完整目录

资料整理详情

1.深入解析微信 MMKV 源码

  • 获取 MMKV 对象
  • 修改数据写入
  • Protobuf 处理
  • Protobuf 实现
  • 跨进程锁实现
  • 文件锁封装

2.深入解析阿里巴巴路由框架 ARouter 源码

  • 初始化
  • 路由跳转
  • 总结

3.深入解析 AsyncTask 源码(一款 Android 内置的异步任务执行库)

  • 功能概述
  • 创建
  • 执行
  • 取消
  • 线程池
  • 不足之处
  • 总结

4.深入解析 Volley 源码(一款 Google 推出的网络请求框架)

  • Volley
  • RequestQueue
  • ExecutorDelivery
  • Request

5.深入解析 Retrofit 源码

  • 目录
  • 源码分析

6.深入解析 OkHttp 源码

  • OkHttp 3.7 源码分析(一)——整体架构
  • 总体架构
  • kHttp 3.7 源码分析(二)——拦截器 &一个实际网络请求的实现
  • OkHttp 3.7 源码分析(三)——任务队
  • OkHttp 3.7 源码分析(四)——缓存策
  • OkHttp 3.7 源码分析(五)——连接池

7.深入解析 ButterKnife 源码

8.深入解析 Okio 源码(一套简洁高效的 I/O 库)

9.深入解析 SharedPreferences 源码

10.深入解析 EventBus 源码

11.Android 自定义注解初探

12.View 的工作机制源码分析

13.Android 触摸事件分发机制源码分析

14.Android 按键事件分发机制源码分析

15.深入解析 Handler 源码

16.深入解析 Binder 源码

17.深入解析 JNI 源码

18.深入解析 Glide 源码

全文508页,共计十八项项目源码的解析精编,碍于篇幅原因,本文就不全部展示了。

想要的直接私信我关键字【源码】即可。

立即获取

Android开发之路并不简单,我们要学的东西不仅仅只有表面的技术,还要深入底层,弄明白下面的原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足,才能突破瓶颈走的更长更远!

千里之行始于足下,愿你我共勉。

资源16 GitHub收藏和深度学习框架,贡献率最高

大数据文摘作品

编译:惊蛰、什锦甜、蒋宝尚

深度学习是一种基于对数据进行表证学习的机器学习方法,近些年不断发展并广受欢迎。

作为一个相对较新的概念,对于无论是想要进入该领域的初学者,还是已经熟知方法的老手来说,触手可及的学习资源太丰富了。

为了不被日新月异的技术和潮流所淘汰,积极参与深度学习社区中开源项目的学习和互动是个很好的方法。

在本文中文摘菌将为大家详细介绍16种GitHub中最受欢迎的深度学习开源平台和开源库,除此之外,还有些比较不错的平台和框架虽然没有进入榜单,文摘菌也列了出来,供大家参考。

GitHub收藏和贡献率最高的16个开源深度学习框架,圆圈的颜色越偏绿色表示框架越新,颜色越偏蓝色表明框架的时间越早。

从上图可知,TensorFlow高居榜首,第二名和第三名的是分别是Keras和Caffe。下面文摘菌就将这些资源分享给大家。

16个最棒的深度学习开源框架和平台

TensorFlow

TensorFlow最初由谷歌的Machine Intelligence research organization 中Google Brain Team的研究人员和工程师开发的。这个框架旨在方便研究人员对机器学习的研究,并简化从研究模型到实际生产的迁移的过程。

收藏: 96655, 贡献人数: 1432, 程序提交次数: 31714, 建立日期: 2015年11月1日。

链接:

https://github.com/tensorflow/tensorflow

Keras

Keras是用Python编写的高级神经网络的API,能够和TensorFlow,CNTK或Theano配合使用。

收藏: 28385, 贡献人数: 653, 程序提交次数: 4468, 建立日期: 2015年3月22日。

链接:

https://github.com/keras-team/keras

Caffe

Caffe是一个重在表达性、速度和模块化的深度学习框架,它由Berkeley Vision and Learning Center(伯克利视觉和学习中心)和社区贡献者共同开发。

收藏: 23750, 贡献人数: 267, 程序提交次数: 4128, 建立日期: 2015年9月8日。

链接:

https://github.com/BVLC/caffe

Microsoft Cognitive Toolkit

Microsoft Cognitive Toolkit(以前叫做CNTK)是一个统一的深度学习工具集,它将神经网络描述为一系列通过有向图表示的计算步骤。

收藏: 14243, 贡献人数: 174, 程序提交次数: 15613, 建立日期: 2014年7月27日。

链接:

https://github.com/Microsoft/CNTK

PyTorch

PyTorch是与Python相融合的具有强大的GPU支持的张量计算和动态神经网络的框架。

收藏: 14101, 贡献人数: 601, 程序提交次数: 10733, 建立日期: 2012年1月22日。

链接:

https://github.com/pytorch/pytorch

Apache MXnet

Apache MXnet是为了提高效率和灵活性而设计的深度学习框架。它允许使用者将符号编程和命令式编程混合使用,从而最大限度地提高效率和生产力。

收藏: 13699, 贡献人数: 516, 程序提交次数: 6953, 建立日期: 2015年4月26日。

链接:

https://github.com/apache/incubator-mxnet

DeepLearning4J

DeepLearning4J和ND4J,DataVec,Arbiter以及RL4J一样,都是Skymind Intelligence Layer的一部分。它是用Java和Scala编写的开源的分布式神经网络库,并获得了Apache 2.0的认证。

收藏:8725, 贡献人数: 141, 程序提交次数: 9647, 建立日期: 2013年11月24日。

链接:

https://github.com/deeplearning4j/deeplearning4j

Theano

Theano可以高效地处理用户定义、优化以及计算有关多维数组的数学表达式。 但是在2017年9月,Theano宣布在1.0版发布后不会再有进一步的重大进展。不过不要失望,Theano仍然是一个非常强大的库足以支撑你进行深度学习方面的研究。

收藏: 8141, 贡献人数: 329, 程序提交次数:27974, 建立日期: 2008年1月6日。

链接:

https://github.com/Theano/Theano

TFLearn

TFLearn是一种模块化且透明的深度学习库,它建立在TensorFlow之上,旨在为TensorFlow提供更高级别的API,以方便和加快实验研究,并保持完全的透明性和兼容性。

收藏: 7933, 贡献人数: 111, 程序提交次数: 589, 建立日期:2016年3月27日。

链接:

https://github.com/tflearn/tflearn

Torch

Torch是Torch7中的主要软件包,其中定义了用于多维张量的数据结构和数学运算。此外,它还提供许多用于访问文件,序列化任意类型的对象等的实用软件。

收藏: 7834, 贡献人数: 133, 程序提交次数: 1335, 建立日期:2012年1月22日。

链接:

https://github.com/torch/torch7

Caffe2

Caffe2是一个轻量级的深度学习框架,具有模块化和可扩展性等特点。它在原来的Caffe的基础上进行改进,提高了它的表达性,速度和模块化。

收藏: 7813, 贡献人数: 187, 程序提交次数: 3678, 建立日期:2015年1月21日。

链接:

https://github.com/caffe2/caffe2

PaddlePaddle

PaddlePaddle(平行分布式深度学习)是一个易于使用的高效、灵活、可扩展的深度学习平台。它最初是由百度科学家和工程师们开发的,旨在将深度学习应用于百度的众多产品中。

收藏: 6726, 贡献人数: 120, 程序提交次数: 13733, 建立日期:2016年8月28日。

链接:

https://github.com/PaddlePaddle/Paddle

DLib

DLib是包含机器学习算法和工具的现代化C ++工具包,用来基于C ++开发复杂的软件从而解决实际问题。

收藏: 4676, 贡献人数: 107, 程序提交次数: 7276, 建立日期:2008年4月27日。

链接:

https://github.com/davisking/dlib

Chainer

Chainer是基于python用于深度学习模型中的独立的开源框架,它提供灵活、直观、高性能的手段来实现全面的深度学习模型,包括最新出现的递归神经网络(recurrent neural networks)和变分自动编码器(variational auto-encoders)。

收藏: 3685, 贡献人数: 160, 程序提交次数: 13700, 建立日期: 2015年4月12日。

链接:

https://github.com/chainer/chainer

Neon

Neon是Nervana开发的基于Python的深度学习库。它易于使用,同时性能也处于最高水准。

收藏: 3466, 贡献人数: 77, 程序提交次数: 1112, 建立日期: 2015年5月3日。

链接:

https://github.com/NervanaSystems/neon

Lasagne

Lasagne是一个轻量级的库,可用于在Theano上建立和训练神经网络。

收藏: 3417, 贡献人数:64, 程序提交次数: 1150, 建立日期:2014年9月7日。

链接:

https://github.com/Lasagne/Lasagne

其他选择

  • H2O.ai

    https://github.com/h2oai/h2o-3

  • PyLearn

    https://github.com/lisa-lab/pylearn2

  • BigDL

    https://github.com/intel-analytics/BigDL

  • Shogun

    https://github.com/shogun-toolbox/shogun

  • Apache SINGA

    https://github.com/apache/incubator-singa

  • Blocks

    https://github.com/mila-udem/blocks

  • Mocha

    https://github.com/pluskid/Mocha.jl

支持Android 5.1 1!发布了新版本的ArtifactXPosed框架

【PConline 资讯】Xposed框架更新支持安卓5.1.1了!如果你是一名资深安卓玩家,你可能会听说过Xposed框架的鼎鼎大名。Xposed框架可谓是安卓上最神奇最强大的App之一,通过Xposed框架,可以安装很多功能不可思议的App模块,实现一般App无法实现的功能。笔者曾经撰文介绍过Xposed框架,详情可以。Xposed框架近日发布最新版,支持最新的安卓系统5.1.1,如果你有需求,可以点此进入XDA上的原帖查看。

Xposed框架支持安卓5.1.1

由于安卓5.0以后的版本使用了全新的ART运行环境,所以原本基于Dalvik虚拟机的Xposed框架无法正常运行。经过开发者一番努力后,Xposed框架终于能够支持安卓5.0,随着版本的更新又支持了安卓5.1。现在,最新版的Xposed框架可以支持安卓5.1.1,不过安装上还是比安卓4.×时代显得麻烦。要在安卓5.1.1中使用Xposed框架,需要先用第三方Recovery刷入zip包,再安装相应的apk,这相信难不到经常刷机的玩家。

目前Nexus 7、Nexus 9以及Nexus 10平板已经更新到了安卓5.1.1,新版的Xposed框架应该可以在这些设备的新系统中工作。Google近日也会为Nexus手机提供安卓5.1.1升级,Nexus 4、5、6的用户可以耐心等候。

【推荐】用PConline官方客户端下载

相关阅读:

低头族请注意用眼!用App保护你的视力

Google发布Nexus 9安卓5.1.1系统更新

高端大气上档次!用签字加密手机的资料

安卓6.0将至?Google I/O或发布安卓M