Quantcast
Channel: 英特尔开发人员专区文章
Viewing all 583 articles
Browse latest View live

极智未来·Intel寻人工智能开发者入围项目新鲜出炉!

$
0
0

小伙伴们,经过重重评选
极智未来·Intel寻人工智能开发者
入围项目终于千呼万唤始出来啦!

什么?你说你不知道这是什么活动
快来戳这儿回顾一下本次活动吧
《极智未来·Intel启动人工智能开发者招募计划》

活动发布后,收到的投递项目类型十分广泛
经过Intel技术组的仔细评选
最终,以下项目入围了本次项目评选
入围项目将获得神秘大礼包哦
此外相匹配的项目也将得到Intel全方位支持

(以下排名不分先后)

在自身领域不断推陈出新的
 

山东大正机械

大正机械是一家自主设计、生产造纸机的专业公司。 烘缸是造纸机的核心部件,目前烘缸检验检测均依靠人工,有很大的主观性,且检测效率低下。大正机械在此领域研发了“基于计算机视觉和人工智能的烘缸检测系统”,利用计算机及其人工智能的力量,自动识别、判定缺陷,以保证烘缸检验检测的客观性、实时性和高效性。
 

走在BIM&VR前沿的
 

华图视景数字科技

华图视景专注于国内BIM技术的应用与推广、工业与民用建筑可视化运维管理系统、虚拟现实VR内容的开发和探索,致力于提升建筑工程行业信息化技术水平,立志做中国国内工程建设领域BIM+虚拟现实VR的领跑者。
 

以后可以让你的每个家具都会说话的
 

小橘灯科技

小橘灯科技致力于研发智能硬件语音模块,提供传统家电厂商提供智能化接入,中小智能家居品牌商产品快速落地以及高集成度低成本的pcba,turnkey解决方案。
小橘灯掌握核心的推荐算法,精准的提供客户需要的语音内容和实用服务。对特定场景ASR和NLP,结合深度学习与传统算法,实现产品的完美落地。小橘灯还可以完成从产品设计、开发到生产一条龙服务。
 

钟情于机器学习并在多领域多栖发展的
 

习悦信息技术

珠海习悦信息技术有限公司以机器学习为核心技术引擎,长期致力于人工智能与计算机视觉产品的研发与服务。公司产品包含云端业务与终端业务两大方向,产品应用涵盖人脸识别、智慧交通、人机交互等多个领域,目前已形成较为完整的产品体系。
 

能够为互联网公司提供智能运维测试的

班默科技

北京班墨科技是国内领先的互联网测试公司,目前正在运营国内最大的众包测试平台"人人测"以及云测试平台"班墨云测试"以及最新推出的“灵鸢”人工智能测试平台。
其中“灵鸢”人工智能测试平台在为广大的软件企业以及APP开发者提供测试服务、种子用户获取以及推广服务,吸引了大量C端用户在平台上完成测试任务并获得奖励的同时,降低企业在测试环节中的投入。
 

人工智能已成为当下时代新风口
人工智能各个领域也在蓬勃发展
猛戳下方二维码,关注Intel人工智能脚步


利用英特尔® 数据分析加速库增强孤立点检测

$
0
0

简介

信用卡公司如何检测欺诈和滥用?网络管理员如何发现入侵?科学家如何了解他们的实验是否正常运行?

为了实现上述目标,他们会对数据集进行分析,寻找异常的数据点。例如,信用卡公司寻找某些交易中非正常的高收费或奇怪的购买行为。上述情形可能表明信用卡被盗。网络管理员搜索日志文件,监督网络上的不规则活动,如某些地址的非正常加载或来自外地 IP 地址的网络访问,这些是存在网络入侵风险的最好证明。同样地,科学家查看数据是否反常,是否超出预期的范围,并以此作为衡量实验非正常运行的指标。

这些反常或不规则的活动被称为孤立点,也被称为异常现象 (anomalies)。本文描述了在数据中检测孤立点 1的各种方法,以及英特尔® 数据分析加速库(英特尔® DAAL)2如何帮助优化孤立点检测,前提需要在配备了英特尔® 至强® 处理器的系统上运行英特尔® DAAL。

什么是孤立点?

孤立点是一个数据点,与其他数据存在显著差异(异常或不规则),或偏离其他数据(见图 1)。


图 1:孤立点案例 #1.

每个紫点代表了数据集中的一个数据点。由于图中有两个数据点与其它数据点的距离非常远,可以判定这两个数据点为孤立点。


图 2:孤立点案例 #2.

图 2 显示了另一种孤立点案例。在本案例中,数据集分为三组(集群)。不在三组范围内的任何数据点均被视为孤立点。


图 3:孤立点案例 #3.

图 3 显示了第三类孤立点案例,尽管图 3 中的数据集也被分为不同的组,但是图 3 和图 2 的案例不同,这是因为数据点的密度不同。在图 2 中,各组间的数据点几乎均匀分布,但是在图 3 中,各组间的数据点密度不同。

孤立点是如何产生的?

孤立点有利也有弊。通过检测网络中的不规则活动(孤立点),网络管理员能够提前发现并阻止数据入侵。另一方面,检测并清除孤立点有助于消除或最大限度降低对计算结果的影响。孤立点能够扭曲或误导机器学习 3的训练过程,造成训练时间变长、模型准确性下降。例如,在 K-means 集群算法的示例中,数据集中的孤立点将导致集群的中心偏离预定位置。

孤立点产生的常见原因包括:

  • 数据采集错误:数据采集设备可能受噪音的影响收集异常数据。
  • 数据输入错误:输入了错误数据。例如,错误地输入某所房屋的售价可能导致房屋价格超出房屋所在社区的平均价格范围。
  • 选择类型错误:如高中生的身高,在某些高中,打篮球的学生的身高明显高于他们的同学,这些学生的身高就是孤立点。为了确保结果正确,测量整个学生群体的身高时,应该单独测量篮球队队员的身高。
  • 转换错误:从多个来源中提取数据时,有可能产生操作或提取错误,最终引起孤立点。

检测孤立点的方法

计划数据集,然后查看图表(相似于图 1 到图 3 所示的内容)是检测孤立点的常见方法。

在第二版《孤立点分析》4一书中,Charu C. Aggarwal 提供了检测孤立点的以下方法:

  • 概率模型
  • 线性模型
  • 近距离模型
  • 高维度孤立点检测

检测孤立点的应用

由于借助孤立点检测方法能够检测出奇怪或异常的数据,这些方法被用于:

  • 在分析网络安全时,检测不规则的活动和奇怪的地址
  • 通过观察反常的购物模式或收费过高的交易,确定信用卡欺诈
  • 通过发现反常的症状或测试结果,诊断患者存在的潜在健康问题
  • 通过分析异常数据(与其他球员的数据相比),发掘优秀球员

本文只列举了孤立点检测方法的几个应用,还有很多没有提到。

英特尔® 数据分析加速库

英特尔 DAAL 是一个包含众多基本构建模块的库,面向数据分析和机器学习而优化。这些基本构建模块经过高度优化,能适应最新版英特尔® 处理器的全新特性。本文中,我们利用英特尔 DAAL 的 Python* API 来展示如何调用孤立点检测函数。遵循英特尔 DAAL 文档 5中的说明安装 Python* API。

利用英特尔数据分析加速库中的孤立点检测方法

《英特尔® DAAL 手册》介绍了什么是单变量孤立点并提供了定义孤立点区域的公式,原文如下所示:

“规定集合 X 代表 p 个维数中的 n 个特征向量 x 1= (x 11,…,x 1p ), ..., x n = (x n1,…,x np ),问题是需要确认不属于底层分配的向量。单变量孤立点检测算法单独考虑每个特性。单变量孤立点检测方法可能包含参数,假设一个数据集的已知基本分配,并定义孤立点区域,属于这个区域的观察被标记为孤立点。孤立点区域的定义与假设的基本数据分配相连。以下是面向单变量孤立点检测的孤立点区域示例:

m n和 σ n是指定数据集的平均值(稳健)估计和标准偏差,α n是置信系数,g (n, α n ) 定义了区域的限制,应该调整为观察数量。”

本章节展示了如何利用英特尔 DAAL 在 Python 6中调用孤立点方法。

从英特尔 DAAL 中调用单变量孤立点检测算法的步骤如下所示:

  1. 输入 from 命令以导入必要的程序包,并导入
    1. 执行如下命令,导入英特尔 DAAL 数值表:

      from daal.data_management import FileDataSource, writeOnly, DataSourceIface, BlockDescriptor_Float64

    2. 利用以下命令导入单变量孤立点检测算法:

      from daal.algorithms.univariate_outlier_detection import InitIface, Batch_Float64DefaultDense, data, weights

  2. 如果数据输入来源于 .csv 文件,初始化文件数据来源:
    		DataSet = FileDataSource(
    		    trainDatasetFileName, DataSourceIface.doAllocateNumericTable,
    		    DataSourceIface.doDictionaryFromContext
    		  )
  3. 加载输入数据:
    		DataSet.loadDataBlock()
    		nFeatures = DataSet.getNumberOfColumns()
  4. 创建一个函数算法:
    1. 首先创建一个算法对象

      algorithm = Batch_Float64DefaultDense()

    2. 将数据集输入算法

      algorithm.input.set(data, DataSet.getNumericTable())

  5. 计算孤立点并得出结论:

    results = algorithm.compute()

  6. 利用以下命令打印结果:

    printNumericTable(results.get(weights), “outlier results“)

注:UCI 机器学习存储库提供一些常用的数据集。7

结论

孤立点检测在欺诈检测、网络安全等领域中发挥重要的作用。英特尔 DAAL 利用未来英特尔至强处理器的全新特性优化了孤立点检测方法,只需在配备上述处理器的计算机系统上运行这些方法,便可实现优化。

参考资料

1.一般孤立点检测

2.英特尔 DAAL 简介

3.维基百科 – 机器学习

4.孤立点检测

5.如何在 Linux* 中安装英特尔 DAAL 的 Python 版本

6.Python 网站

7.常用数据集

Nervana 引擎为深度学习带来了难以置信的速度!

$
0
0

NERVANA 已经加入 英特尔

原始文章发表于 Nervana 网站: Nervana 引擎为深度学习带来了难以置信的速度 .

请访问  Nervana 主页了解关于 英特尔 Nervana 深度学习技术的更多信息。

目前,Nervana 正在开发 Nervana 引擎,一种针对深度学习定制和优化的特定应用集成电路 (ASIC)。

训练深度神经网络涉及大量计算密集型操作,包括张量的矩阵乘法 和卷积。由于图形处理单元 (GPU) 最初专为电子游戏而设计,在电子游戏中,屏幕上对象的移动受矢量和线性代数的控制,因此,相比 CPU,GPU 更适合上述操作。GPU 成为了面向深度学习的可靠计算平台。但是,由于数值精度、控制逻辑、高速缓存和其他 GPU 架构元素均面向电子游戏而非深度学习优化,GPU 仍存在较大的改进空间。

Nervana 生产出了全球最快的面向深度学习的 GPU 内核,它比其他制造商更了解这些限制,也知道如何高效解决这些问题。设计 Nervana 引擎时,我们摒弃了 GPU 模式,重新开始。我们分析了最常见的深度神经网络,确定了实施关键操作的最佳架构。我们甚至分析并优化了核心数值格式,创建了 FlexPoint™,后者实现了最高的精度,只占用 16 位以内的存储,实现了高内存带宽和算法性能的完美结合。我们又添加了充足的灵活性,以确保架构满足未来的需求。Nervana 引擎仅包含深度学习所需的全部组件,它的强大性能将确保 Nervana 深度学习平台依然是全球速度最快的平台。所以,您现在准备好体验光速般的深度学习了吗?!

高带宽内存实现了超快速的数据访问

训练深度神经网络需要传输大量的数据,目前的内存技术无法满足这样的要求。在训练过程中访问了训练数据并更新了模型参数。DDR4 SDRAM 存储容量较高,但是带宽有限。GDDR5 SDRAM 速度更快,但是内存容量有限。Nervana 引擎采用了全新的内存技术 - 高带宽内存 (HBM),兼具大容量和高速的两大优势。HBM 为 Nervana 引擎带来了 32GB 的封装存储和超快速的 8 TB/秒内存访问带宽。

Nervana 引擎的 HBM 内存通过芯片堆叠实现了高容量。由于 HBM 芯片由 8 个单独的 1 GB 内存芯片堆叠而成,因此,单个 HBM 芯片可以存储高达 8GB 的数据。Nervana 引擎包含了 4 个 HBM 堆栈,提供了 32GB 的封装存储。HBM 的高速(带宽)主要借助 2.5D 制程(一种新的制程工艺)实现的。该制程工艺极大缩小了内存芯片底部的引脚间距,因此能够容纳更多的数据通道。2.5D 制程显著提高了 Nervana 引擎的内存访问速度。性能提升的同时,占用了很小的芯片空间,为新计算电路预留更大的空间,使电路能够充分利用提升后的内存容量和带宽。

前所未有的计算能力

Nervana 引擎设计只包括与深度学习相关的内存和计算元素。例如,Nervana 引擎不包括管理高速缓存层级,内存管理由软件执行。这是一个高效的深度学习策略,执行前对操作和内存访问进行了全面的规定。通过消除高速缓存控制器和一致性逻辑,该策略还提升了芯片区域的使用效率。此外,片上内存的软件管理确保了高优先级数据(如模型权重)不被清除。

面向深度学习优化的设计最终为 Nervana 引擎带来了前所未有的计算密度,在计算能力方面,比目前一流的 GPU 高出几个数量级。Nervana 能取得这么大的突破,主要因为它利用商用 28 纳米制程技术建造了 ASIC,未来还可以缩小至 16 纳米,存在继续改进的空间。

吞吐率接近理论极限

我们之前讨论过,数据传输通常是深度学习的一个瓶颈。鉴于这种依赖性,很难确保计算不会因为等待数据而闲置。Nervana 引擎具有面向计算和数据管理的独立管线,不断向计算传输新的数据,确保计算元素一直保持工作状态。管线隔离和充足的本地内存意味着在多数情况下,Nervana 引擎几乎能达到理论最大吞吐率。

内置网络带来了前所未有的速度和模型的可扩展性

Nervana 引擎进行了重新设计,以支持真正的模型并行性。Nervana 引擎包含 6 个双向高带宽链接,支持以无缝的方式实现机箱内部或机箱之间的芯片互联。如此一来,只需为任务分配更多的计算或将模型扩展至前所未有的尺寸,用户便可在当前模型上获得线性加速。例如,在环面配置中相互连接 8 个 ASIC(如下所示),将实现接近 8 倍的线性性能加速。从概念上讲,环面相当于一个大型的处理器:

这种加速功能是 Nervana 所独有的。竞争系统使用了面向全部通信(包括对等和主机到卡的通信)的超额定购、低带宽 PCIe 总线。这款超额订购 PCIe 链接限制了通过添加硬件提升性能的能力。此外,当前系统需要价格高昂且带宽有限的 infiniband 或面向机箱到机箱通信的以太网链接,极大地降低了扩展至一个以上主板或机箱的可能性。

Nervana 引擎提供高带宽内存、前所未有的计算密度、隔离的数据和计算管线以及内置网络,将实现行业内最大规模的深度学习支持。
 

关于作者:

Carey Kloss 是 Nervana 公司的硬件副总裁,1996 年起,他开始投身于芯片行业,在新创公司和上市公司均有任职经验。他非常期待将全新的创新型芯片技术应用于深度学习。

 

利用二进制算法提升神经网络的速度

$
0
0

NERVANA 已经加入了 英特尔

原始文章发布于  Nervana 网站: 利用二进制算法提升神经网络的速度. 请转至   Nervana 主页  获取关于 英特尔 Nervana 深度学习技术的更多信息。

Nervana 致力于改善算法和硬件以及加快神经网络的速度。低精度算法是令人倍感兴奋的一个研究领域。本文重点介绍了 二值化神经网络 (BNN)(一种低精度网络)和它的基本概念,还简要概述了 Neon CPU 和 GPU 实施。BNN 在多个数据集上实现了与标准神经网络不相上下的准确性。

BNN 在所有计算中使用了二进制权重和激活。浮点算法存在于所有深度学习计算中,包括计算梯度、应用参数更新 和计算激活。但是,32 位浮点乘法的成本非常高昂。在 BNN 中,浮点乘法被逐位 XNOR 所替代,留下了左右位移。从硬件的角度看,这点极具吸引力:以较低的成本实施二进制操作,同时提升计算效率。


来源:深度学习资源
图 1:BNN 使用二进制权重和激活,将 sign 函数用作激活函数,以确保二进制值激活。

相比训练,这些优势在推断中体现得更为明显。实际上,我们发现在训练中,每次迭代(向前传播、向后传播和参数更新)的速度提升了,但是为了达到相同的准确性,BNN 所需的迭代数量多于标准神经网络。对于推断而言,多数乘法降为二进制操作。Courbariaux 等人认为推断的速度高出了 7 倍,具有更高的能效性,且不会损失准确性。这些提升使部署于边缘的推断芯片更具吸引力,如自动驾驶汽车、无人机和智能手机中的芯片。

在 BNN 中,标准深度学习网络的常见组件被其二进制版本所替换。例如,基于位移的学习速度调度取代了典型的学习速度调度。其它的替换包括二进制线性层、sign 函数、基于位移的 batch norm、基于位移的 AdaMax 和 XNOR 点乘积。这些版本用高效二进制操作替代了浮点乘法,使用了三个基本概念:二值化、位打包、两种位移的大致性能。

二值化

二值化函数是 BNN 的原始操作,负责将权重和激活转换为 -1 和 +1s。这个函数分为两种类型:确定性与随机性。确定性函数基于 sign 确定权重或激活的阙值。

随机函数根据概率选择 -1 和 +1。由于该函数需要随机生成位,更加难以实施。

σ(x) 代表 hard sigmoid 函数。

二值化函数被用作激活函数,应用于所有的权重层。例如,在向前传播中

L 是总层数,Wk和 θk分别代表指定的 k 层中的权重和 batch norm 参数。二值化,尤其是随机二值化,可以被视为一种规整化形式。从概念上讲,它和 Dropout 相似,根据概率设置了更多值的阙值。

对于随机梯度下降 (SGD),许多噪音更新优于单个确切的更新。直观解释了为什么 BNN 效果显著:尽管二值化降低了更新的精度,噪音最终得到平衡,更新也逐渐回归正确的方向。

需要着重指出的是,只对权重和激活实施了二值化,实施对象不包括向后传播过程中更新参数的梯度。实值梯度是 SGD 正常运行所必需的。权重存储于实值累加器中,每次迭代中面向向前传播和梯度计算实施二值化。请访问该链接,了解如何在向后传播过程中减少计算。

位打包

在 BNN 中,需要乘以 -1 和 +1s 矩阵;例如,在向前传播过程中乘以激活和权重。GPU 不支持本地二进制操作。仅需 1 位的情况下,使用 32 位或 16 位造成了极大的浪费。

通过在单个 32 位整数中融合 32 位,模拟二进制算法,然后执行逐位 XNOR 操作,即在 32 个不同二进制操作内两个 32 位整数结果之间的逐位 XNOR。在 -1 到 1 的二进制范围内,XNOR 相当于乘法:如果操作数相同,结果为 1,如果操作数不同,结果为 -1。打包整数属于前期成本,但是每次操作的计算吞吐率提升了 32 倍。

这个概念可以用来实施 XNOR 点乘积,使用点乘积计算包含 -1s 和 +1s 的两个矩阵的乘法。在普通的矩阵乘法中,C = AB,A、B 和 C 是矩阵,结式矩阵 C 的每个元素都由 A 行和 B列之间的点乘积计算。在简单的 CUDA 内核实施中,我们可以看到特定行和列之间的以下关系

XNOR 点乘积在分别在 A 行中横向打包位,在 B 列中纵向打包位,然后利用逐位 XOR 和人口数量操作,如下所示

Ap和 Bp是副本的位打包版。-1s 由 0s 和 1s 表示,为了便于使用,由 1s 表示。累计值稍后在结式矩阵中解包。高效实施了积累、人口数量和 XOR。

两个位移的大致性能

在深度学习中,通常需要缩放值,如随着训练的进行而降低学习速度、计算规模和 batch norm 位移、在学习规则中更新的参数等。这些乘法可以替换为两个二进制位移的大致性能。例如,假如我们需要计算  7*5 的近似值。

AP2 是两个操作符的大致性能,<< 是一个左二进制位移。这个做法非常有吸引力,原因有以下两点:1) 支持极其高效地计算两个操作符的大致性能(请查看 bit twiddling hacks获得灵感);2) 利用左二进制位移和右二进制位移便可轻松实施两个操作符性能的乘法。请查看面向 vanilla 的更新规则 AdaMax,了解如何在实践中应用

gt和 θt是步骤 t 中的梯度和参数,β1和 β2是面向 AdaMax 学习规则的超参数,α 是学习速度。

最后一行的乘法可以替换为两个位移的大致性能,以获得基于位移的 AdaMax 更新规则。

<<>> 是左二进制位移或右二进制位移(取决于 sign)。基于位移的 batch norm 和学习速度调度也不例外。

结论

使用二值化、两个位移的大致性能和位打包,可以将乘法替换为计算速度快、能效高的二进制操作。上述三个概念构成了 BNN 的基础。

Neon 提供了面向 CPU 和 GPU 的启动实施,请访问此处获取。非常欢迎您的反馈和参与,如果您有任何问题,请访问info@nervanasys.com
 

关于作者:

Sathish Nagappan 任职于 Nervana 公司的算法和云团队,他于不久前毕业于斯坦福大学,在大学期间,加入吴恩达的机器学习小组并从事研究。他具有强烈的创业精神、敏锐的设计感和丰富的经验,他从事的领域涵盖从硬件到软件的整个工程堆栈。他非常喜欢艺术、设计、人工智能、电影和 Baltimore Ravens 球队。

 

面向 GEMM 引入新封装的 API

$
0
0

1     面向 GEMM 引入新封装的 API

矩阵-矩阵乘法 (GEMM) 是众多科学、工程和机器学习应用中的重要操作。优化这一操作的需求一直存在,英特尔® 数学核心函数库(英特尔® MKL)提供了并行的高性能 GEMM 实施。为了提供最佳性能,英特尔 MKL 提供的 GEMM 实施通常将原始输入矩阵转换为最适合目标平台的内部数据格式。数据转换(也被称为封装)会产生高昂的费用,尤其在处理具有 1 个或多个小尺寸的输入矩阵时。

英特尔 MKL 2017 引入了 [S,D]GEMM 封装应用编程接口 (API),该接口支持用户将矩阵明确转换为内部封装格式,以及将封装矩阵传输至多个 GEMM 调用。如果在 GEMM 调用之间重复使用输入矩阵(A 或 B),借助这种方法能在多个 GEMM 调用内分摊封装成本。

2      示例

以下 3 个 GEMM 调用使用了相同的 A 矩阵,但是每个调用使用了不同的 B/C 矩阵:

float *A, *B1, *B2, *B3, *C1, *C2, *C3, alpha, beta;

MKL_INT m, n, k, lda, ldb, ldc;

// initialize the pointers and matrix dimensions (skipped for brevity)

sgemm(“T”, “N”, &m, &n, &k, &alpha, A, &lda, B1, &ldb, &beta, C1, &ldc);

sgemm(“T”, “N”, &m, &n, &k, &alpha, A, &lda, B2, &ldb, &beta, C2, &ldc);

sgemm(“T”, “N”, &m, &n, &k, &alpha, A, &lda, B3, &ldb, &beta, C3, &ldc);

在每个 sgemm 调用中,A 矩阵被转换为内部封装数据格式。如果 n 较小(B/C 的列数),会导致 3 次封装矩阵的相对成本较高。通过单次封装 A 矩阵,并在 3 个连续的 GEMM 调用内使用经过封装的矩阵,可以最大限度地降低成本,其代码示例如下所示:

// allocate memory for packed data format

float *Ap;

Ap = sgemm_alloc(“A”, &m, &n, &k);

// transform A into packed format

sgemm_pack(“A”, “T”, &m, &n, &k, &alpha, A, &lda, Ap);

// SGEMM computations are performed using the packed A matrix:Ap

sgemm_compute(“P”, “N”, &m, &n, &k, Ap, &lda, B1, &ldb, &beta, C1, &ldc);

sgemm_compute(“P”, “N”, &m, &n, &k, Ap, &lda, B2, &ldb, &beta, C2, &ldc);

sgemm_compute(“P”, “N”, &m, &n, &k, Ap, &lda, B3, &ldb, &beta, C3, &ldc);

// release the memory for Ap

sgemm_free(Ap);

为了支持面向 GEMM 的封装 API,上述代码示例使用了 4 个新函数:sgemm_alloc、sgemm_pack、sgemm_compute 和 sgemm_free。首先,利用 sgemm_alloc 分配封装格式所需的内存,该函数接收一个确定封装矩阵(在本示例中为 A)的字符参数和三个表示矩阵尺寸的整数参数。然后,sgemm_pack 将原始 A 矩阵转换为封装格式 Ap 并执行 alpha 缩放。未更改原始 A 矩阵。三个 sgemm 调用被替换为三个 sgemm_compute 调用,后者处理封装矩阵并假设 alpha=1.0。输入 sgemm_compute 的前两个字符参数表示 A 矩阵为封装格式 (“P”),B 矩阵为非转置 column major 格式 (“N”)。最终,通过调用 sgemm_free 释放了分配给 Ap 的内存。

从本示例可以看出,GEMM 封装 API 消除了在 3 个矩阵-矩阵乘法操作中两次封装矩阵 A 的成本。如果在多个 GEMM 调用之间重复使用 A 和/或 B 输入矩阵,封装 API 可以消除该输入矩阵的数据转换成本。

3      性能

下表显示了利用封装 API 在英特尔® 至强融核™ 处理器 7250 上取得的性能提升。假设如果使用相同的 A 矩阵的 SGEMM 调用数量很多,可以完全分摊封装成本。本文还提供了普通 SGEMM 调用的性能,以进行对比。

4      实施要点

建议利用相同数量的线程调用 gemm_pack 和 gemm_compute,以达到最佳性能。需要指出的是,如果使用相同的 A 或 B 矩阵的 GEMM 调用数量较少,封装 API 可能提供微乎其微的性能优势。

gemm_alloc 例程分配的内存与原始输入矩阵的规模相当。这意味着对于大型输入矩阵,应用对内存的要求将显著增大。

在英特尔 MKL 2017 中,只面向 SGEMM 和 DGEMM 实施 GEMM 封装 API。它们适用于所有的英特尔架构,但是只面向 64 位英特尔® AVX2 及更高版本进行了优化。

5      结论

[S,D]对于使用相同输入矩阵的多个 GEMM 调用,利用 GEMM 封装 API 能够最大限度地降低数据封装成本。如性能图表所示,如果在多个 GEMM 调用中矩阵得到充分地重复使用,调用它们能显著提升性能。可以在英特尔 MKL 2017 中获取这些封装 API,支持 FORTRAN 77 和 CBLAS 两种接口。如欲获取更多文档,请查看英特尔 MKL 开发人员参考。

 

Optimization Notice in English

使用 Underminer Studios 的 MR 配置器工具制作混合现实虚拟现实视频

$
0
0

作者: Timothy Porter,Underminer Studios LLC
编辑: Alexandria Porter,Underminer Studios LLC

我是管线技术美工与效率专家 Timothy Porter。 我负责创建统一的系统,为创意项目提供更快、更直观且更协同的工作流程。 凭借超过 9 年的娱乐业从业经验、电脑动画专业的学士学位以及对技术细节的敏锐度,我用自己在早期职业游戏工作中学习到的经验教训开发了各种解决方案,以简化管线、优化多个平台并创建使团队更强大、更高效的工具。 我拥有一家名为 Underminer Studios的外包与尖端科技公司。

概述

本文将教您如何识别支持混合现实 (MR) 的虚拟现实应用,以及如何在 Unity* 虚拟现实应用中启用 MR 模式。 在文本结尾,您将可以调整自身体验,使用最清晰、最准确的配置制作 MR 绿屏视频。 由于绿屏 MR 对开发人员和内容创建者(如内容传输者或 YouTube 用户)都有用,本文中的信息将从开发者和用户角度出发。 记住,有些信息可能比内容创作者在 MR 中立即开始工作所需的信息要多。 请参考章节标题,以便找到符合您需求的相关信息。 到目前为止,首次设置 MR 体验的过程是一个痛苦冗长的过程。 Underminer Studios 创建了 Underminer Studios MR 配置器工具来完善流程。

Underminer Studios 的 MR 配置器工具

该工具旨在加速 MR 设置的校准。 本文介绍了如何使用该工具并帮助您充分利用 MR 体验。 对于虚拟现实用户和内容传输者来说,制作 MR 视频是向不使用头戴式显示器 (HMD) 的人展示不同视角的好方法。然而对于虚拟现实开发人员来说,MR 视频是制作预告片和展示更全面的 VR 体验的绝佳方法。

Underminer Studios MR 配置器工具将为您提供怎样的帮助?

与相机调准的手动流程相比,这款工具可自动配置控制器/相机偏移,从而大大缩短调准时间。 如果没有这个助手实用程序,您可以从一个空白的 externalcamera.cfg 文件开始,手动调整 x、y 和 z 偏移值,以便使虚拟相机和真实相机对齐。 每次更改时,您必须关闭应用并重启,然后检查对齐,希望您的配置正确,并在需要时重复。 这是一个冗长且不准确的过程。 我们的助手实用程序可简化并自动执行这一对齐过程,让您更轻松地校准 MR 设置。 下载并安装可执行文件,然后下载并遵循阅读指南中的文档。

尽管我们有很多用例来吸引广泛的受众,但开发人员总会不可避免地遇到新的未知需求。 我们打算定期更新工具,如果您有任何工具改进方面的意见,请发送电子邮件至info@underminerstudios.com

如何使用 MR 配置器工具

我们提供了一个便于使用的信息文件,其中包含如何设置应用的各个步骤。该文件包含在MrSetUp.pdf文件中。 您的安装程序中也提供了直接链接。

什么是混合现实?

在这种情况下,混合现实是指从支持 MR 的虚拟现实应用分层到视频中的绿屏背景上的人。 这是向未佩戴虚拟现实头盔的人展示虚拟现实世界的绝佳方式。 用户可以与他人分享其虚拟现实体验,并可以帮助创造一个社交性更强的游戏环境。 一旦您拥有一款支持 MR 的虚拟现实应用,您只需一台合适的相机、一些绿屏材料和一个额外的 Vive* 控制器即可创建自己的 MR 虚拟现实体验。

所需条件

强大的机器

在虚拟现实基础上添加 MR 需要一个高端系统来处理这些应用带来的内在压力。 如果没有足够强大的系统,则可能会出现性能滞后的情况,这可能会降低您的帧速率并带来不太理想的体验,特别是对于佩戴头盔显示器的用户而言。 需要使用高端 PC 提供 MR 体验并避免这些问题。 我在下面提供了一个列表,列出了 MR 体验的最佳系统要求。

支持 MR 的应用

您可以使用以前创建的支持 MR 的项目或自己创建一个项目。 我们将在本节中进行介绍。

如何判断一个虚拟现实应用是否可以使用这种方法

  1. 配置文件

    将名为“externalcamera.cfg”的配置文件放到与虚拟现实可执行文件相同的目录中,查看基于 Unity 的虚拟现实应用是否支持这种 MR 模式。 比如您在 C:\Program Files (x86)\Steam\steamapps\common\APPNAMEHERE\ 目录下有一个游戏。 只需将文件放在该文件夹中即可。 以下是一个原始配置文件的示例:

    x=0
    y=0
    z= 0
    rx=0
    ry=0
    rz=0
    fov=60
    near=0.01
    far=1000

    请注意,这个配置文件立即正常运行的几率几乎为 0。 利用我们的应用进行配置,或查看下面的手动配置部分并按照说明操作。

  2. 连接第三个 Vive 控制器

    连接第三个 Vive 控制器(这个控制器需要通过 USB 插入,因为 SteamVR* 一次只能支持两个无线控制器)。 启动 VR 可执行文件,如果您在桌面上看到一个由四个面板组成的四等分视图, 则该应用应该可以使用这种制作 MR 视频的方法。 如果您没有看到这种由四个面板组成的四等分视图,那么很有可能该应用不是在 Unity 中创建的,或不支持这种 MR 视频方法。 如果您创建了虚拟现实可执行文件,请阅读相关说明,了解如何支持这种 MR 模式。 如果不是您的应用,则可能需要您选择另一个应用来制作 MR 视频。

开发人员和用户

如果您想要在 Unity 内设置 MR,请转至开发人员部分。 如果您想要学习如何玩现成的 MR 游戏,请转至用户部分。 首先我们来介绍开发人员方面,如果您的目标是创造出色的 MR 体验,从此处开始。 稍后我们将学习最终用户方面,如果您的游戏已经配置了开发方面,则可以从这里开始。 我们将限制这一讨论,重点关注如何在 Unity 和 SteamVR 系统内实现 MR,因为创建多个相机和绿屏以及合成它们有多种方法。 我将使用 HTC Vive,我曾看到其他人使用 Oculus Rift* 和 Touch* 控制器,但这不在本文的介绍范围之内。 我们立即开始吧!

开发人员方面

我将首先介绍当前的本机 SteamVR 插件方法。 这种方法可免去系统设置中的许多猜测,为您提供快速、高品质的 MR 设置。 提供的工具位于当前系统之上,通过自动化或助手解决方案减少了流程中的手动或繁琐环节。 如果未涉及您项目所需的特定设置或流程,那么没有必要终止,因为流程的其余部分是完全独立的。

本机(内置)SteamVR MR 概述

发明这一工具的团队真是太棒了。 SteamVR 设置利用剪切面和播放器位置创建多个视图,以此支持 MR 体验。 如果您想使用本机插件并在游戏中启用此功能,您有两个单独选择: +第三个控制器和无第三个控制器。 两者都需要使用 externalcamera.cfg。

使用 externalcamera.cfg 的示例

这一文件作为 externalcamera.cfg 进入项目的根目录。 这一文件会告知系统相机与控制器之间的偏移距离(以米为单位)。

x=0
y=0
z= 0
rx=0
ry=0
rz=0
fov=60
near=0.01
far=100
sceneResolutionScale=0.5

使用什么设置?

使用第三个控制器可让用户移动相机。 如果您打算使用固定式相机,请参见下面的无第三个控制器部分。 如果您的游戏需要移动相机,请参见下面的+第三个控制器部分。

无第三个控制器—本机 SteamVR MR 设置

  1. 使用额外的控制器预制件
  2. 将 SteamVR_Tracked Object (Script) 的索引设为设备 2。

用户需要对上面使用 externalcamera.cfg 的示例部分中涉及的 externalcamera.cfg 进行设置。

注: 这需要始终使用 Unity IDE,除非您按照下面的“如何不使用 Unity IDE”部分操作。

+第三个控制器—本机 SteamVR MR 设置

  1. 使用额外的控制器预制件
  2. 将 SteamVR_Tracked Object (Script) 的索引设为设备 3。

这在概念上很简单。 您只需要一个通过 USB 连接到游戏电脑的额外控制器。

注: 这需要始终使用 Unity IDE,除非您按照下面的“如何不使用 Unity IDE”部分操作。

如何不使用 Unity IDE—本机 SteamVR MR 设置

两者都需要您在编辑器内运行项目。 如果你想制作一个独立版本,那么需要做一些额外的工作。

  1. 在层次结构的根目录中添加 “SteamVR_ExternalCamera” 预制件。
  2. 将 “Controller (third)” 拖入到 [SteamVR] 脚本 “Steam VR_Render” – External Camera。
  3. 在 SteamVR_Render.cs 中添加下列代码:
    	void Awake()
    	{
    	#if (UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
    	    var go = new GameObject("cameraMask");
    	    go.transform.parent = transform;
    	    cameraMask = go.AddComponent<SteamVR_CameraMask>();
    	#endif
    	    if (System.IO.File.Exists(externalCameraConfigPath)) {
    	        {
    	            if (externalCamera == null) {
    	                var prefab = Resources.Load<GameObject>("SteamVR_ExternalCamera");
    	                var instance = Instantiate(prefab);
    	                instance.gameObject.name = "External Camera";
    	            }
    	            externalCamera = instance.transform.GetChild(0).GetComponent<SteamVR_ExternalCamera>();
    	            externalCamera.configPath = externalCameraConfigPath;
    	            externalCamera.ReadConfig();
    	        }
    	    }

用户方面

如果您已经有了一个支持虚拟现实的系统,请跳至下面的运行 MR部分。

系统要求

我在下面添加了高端选项 (a) 和低端选项 (b)。

购物清单:

  1. 绿屏套件

    a. StudioPRO* 3000W 连续输出软盒照明套件,提供 10 英尺 x 12 英尺支持系统,383.95 美元(或类似)。
    b. ePhotoInc* 6 x 9 英尺棉色键背景,18.99 美元。

  2. 额外的控制器

    a. Vive 控制器,129.99 美元。
    b. 这款解决方案不需要额外的控制器,但如果您不是创建游戏的开发人员,则必须保持相机静止不动,并执行如下所述的变通方案。

  3. 相机

    a. Panasonic* HC-V770,带配件包,499.99 美元(或带用于实时相机视图的 HDMI 输出的类似相机;数码单反相机或无镜像数码相机可能行,但请注意,其传感器不适合长期运行,可能会过热。 )

  4. 视频捕捉卡

    a. Magewell* XI100DUSB-HDMI USB 捕捉 HDMI 3.0 - 299.00 美元(或类似的 HDMI 捕捉设备)。

  5. 计算机

    a. 如果您正在阅读这篇文章,那么您可能已经有一台具备虚拟现实功能的 PC。 除了最低虚拟现实规范之外,您将需要一个具备足够能力处理额外工作的系统(在比您需要的录制分辨率高 3 倍的分辨率下运行四等分视图,以及执行图层捕捉、绿屏色度键和 MR 合成)。 推荐使用高端的第六代或更高版本的英特尔® 酷睿™ i7 处理器(例如 7700K 或类似)

  6. 4K 显示器

    a. 鉴于 MR 捕捉四等分视图窗口的方式,您会希望能够在比最终视频输出分辨率高 4 倍的分辨率下运行该窗口。 这意味着,如果您想以 720p 的分辨率录制,则您需要能够在 1440p 分辨率下运行窗口,因为您一次只捕捉窗口的四分之一。 如果您想要以 1080p 的分辨率录制,则需要以 2160p 的分辨率运行窗口。 为此,您将需要一台能够处理这些分辨率的显示器; 或许为 4K 或更高。

关于一些选项的更多信息

  1. 绿屏

    您可以使用户外地毯(如 AstroTurf*)作为背景。 看起来似乎效果不错,应该持续很长一段时间,但实际上任何单一颜色的东西都应该不错。 推荐使用绿色,因为大多数系统(OBS*,或本教程提供的屏幕截图)都用绿色作为剪切或色度键。

  2. 控制器

    如果项目设置不当且需要一个额外的控制器,那么有一个涉及如何在软件中伪造第三个控制器的解决方案。 这个解决方案不在本文的介绍范围内,如果您想尝试一下,请点击此处了解更多信息。

  3. 相机

    使用真正的相机和网络摄像机进行摄像有巨大的差异。 上面列出的摄像机选项中有一些很棒的功能,且不像专业摄像机那么贵。 如果您使用静物相机(数码单反相机或无镜像数码相机),请注意,它们的传感器通常不适合不间断运行,因为可能会过热;这就是为何它们通常有 20 或 30 分钟的录像限制。 请务必小心,不要损害您的设备。

  4. 视频捕捉卡

    如果您使用外部相机,则需要使用捕捉卡才能使相机的 HDMI 输出显示为 PC 的可用源。 上文列出的相机使用 USB,是一款出色的全功能捕捉卡。 与使用与系统相连的内部卡相比,USB 捕捉卡的最大好处是其轻便易携。 若要与发布商、客户或其他开发人员进行现场沟通,您可将其装入一个袋中,向他们发送一个构件并向每个人展示游戏进展。 它可以让您快速传达信息和想法。

  5. 计算机

    我们正在进行的项目是一个计算密集型项目,因此 CPU 选择非常重要。 现代的高端英特尔酷睿 i7 处理器(如 7700K)非常适合这样的项目,因为许多进程是单线程密集型的(如来自 SteamVR 的合成器),高单核性能可起到真正的帮助作用。 使用四核或更高 CPU 可帮助您更好地捕捉、合成和录制 MR 视频。

运行 MR—设置

要查看设置,您只需要下面的 .cfg 文件和一个允许使用 MR 的游戏即可。 其中一些游戏包括 Fantastic Contraption、Job Simulator*、Space Pirate Trainer*、Zen Blade* 和 Tilt Brush* 等。

只有满足这两个要求后,设置视图才会出现:

  1. 在项目的根目录中添加一个名为 externalcamera.cfg 的文件。
  2. 将第三个控制器连接到系统。

运行 MR—步骤

注: 在使用以下步骤配置 .cfg 文件之前,这些步骤将无法使体验与现实保持一致。

  1. 关闭 SteamVR

    如果您打开 SteamVR,则会对其他进程造成影响,因此最好关闭。 同样,如果您以后遇到问题,重启将起到帮助作用。

  2. 将 externalcamera.cfg 文件放在项目的根目录中

    接下来,您需要将文件放在项目根目录的正确位置。 如果发现您的项目没有显示四面板四分屏,那么您需要在检查控制器之后验证根位置。

  3. 设置您的绿屏和灯

    您需要将人合成到虚拟现实环境中。 为此,您需要一个绿屏设置,将人从真实世界中移出并放入虚拟现实世界。

  4. 将相机连接到电脑/捕捉卡

    应对同时运行虚拟现实和 MR 所产生的额外开销基本上需要使用捕捉卡,仅使用网络摄像头是不够的。 另外,捕捉卡可让您从辅助摄像机中导入视频。

  5. 将控制器固定在相机上

    系统总是需要定位相机,我们通过让系统跟踪 Vive 控制器来实现这一点。 上面的配置文件基于 Vive 控制器相对于所连接相机的位置向系统提供偏移和相机信息。 控制器越紧越好。

  6. 拔下连接到系统的所有控制器

    SteamVR 在这个过程中会产生混乱。 如果您加入项目并发现第三台相机连接了错误的控制器,请拔下第三个控制器并重新插上电源,这样可以解决问题。

  7. 打开 SteamVR

    现在我们可以启动 SteamVR 了。

  8. 打开未连接到相机的两个控制器

    我们只想打开未连接的控制器,以便它们到达 SteamVR 手机插槽中的正确位置。 这是关键的一步,请务必进行这一步。 我还建议在灯塔上直接挥动控制器。

  9. 将连接到相机的控制器插入系统

    现在 Steam 已经知道前两个控制器的位置,您可以接入第三个控制器了。 如前所述,如果您加入项目并发现第三台相机连接了错误的控制器,请拔下第三个控制器并重新插上电源。

  10. 双击您所选的游戏

    这可以让您以最高分辨率打开项目。 出于某些原因,SteamVR 还会对管理员运行的应用给予优惠待遇,因此这应该有所帮助。

  11. 选择所需分辨率(比您所需的录制分辨率高 3 倍)

    这种情况可以使用 4K 或更高分辨率的显示器。 由于您只捕捉窗口的四分之一(并且合成多个图层),因此您需要在此处选择正确的窗口大小。 如果您想要以 720p 的分辨率录像,请选择 2560 x 1440。 如果您想要以 1080p 的分辨率录像,请选择 3840 x 2160。 您可能需要尝试不同的录像分辨率,具体取决于您的系统性能和所需的录像质量。

  12. 打开 OBS 或 XSplit*

    接下来我们将进入实时合成部分的内容。 尽管其他程序也可能有效,但这些程序都经过 MR 合成方面的测试。

  13. 添加裁剪的左上角,并将右上角作为 alpha;将这一图层标记为 “前景”

    本部分将介绍人的合成。 如果您没有时间将手机完全匹配到虚拟现实空间,请为控制器选择一个使用大符号的皮肤。 这将隐藏所有内容并非完全匹配的事实。 这是一份展示如何在 teamVR 中更改控制器皮肤的指南。

  14. 从您的相机添加视频流,并用色度过滤器清除背景;将这个视频流标记为“Live”

    将真人添加到虚拟现实环境是本项目最重要的部分。 根据您使用的程序,您可以通过多种方式来执行此操作。 下面是 XSplit 的屏幕截图,用来展示您可以对图层进行色键处理,从图像中删除单个颜色。

  15. 添加左下角;将这个图层标记为“背景”

    我们将这个图层放在您用来合成的程序的底部位置。 如果背景不可见,重复上述步骤。

  16. 关闭游戏并对配置文件进行配置

    若要创建配置文件,请使用本文开头介绍的工具或按照下面的内容操作。 提醒: 手动配置不仅难以正确完成,而且也是一个缓慢而费力的任务。 每次发生更改时,您都需要重启程序。 设置的平均时间约为 1 小时。 我们已经使用 MR 配置器工具将流程平均缩短了三分钟。 它也更加准确,因为安装时间长通常会导致人们在完成配置之前放弃。

如何在 externalcamera.cfg 中手动计算信息

x=0
y=0
z= 0
rx=0
ry=0
rz=0
fov=60
near=0.01
far=100
sceneResolutionScale=0.5

配置

注: 记住,您可以使用我们的工具跳过整个部分。

  1. 视野 (FOV) – 这必须是垂直 FOV

    FOV 是设置中难度最大的;先找出 FOV。 大多数相机制造商提供相机的 FOV 值,但这不是垂直 FOV。 这些技术中的大多数来自相机世界。 这是一篇关于如何找到 FOV的文章。

    注: 相机的 FOV 取决于焦距。 一旦完成设置,不要放大或缩小相机!

  2. 旋转

    RX、RY、RZ—这些是旋转角度。 0,0,0 表示手机是否与相机持平。 Y+ 是向上,Z+ 是向前,X+ 是向左。 请注意,这些是度数。

  3. 距离

    X、Y 和 Z 应使用卷尺进行测量。 记住,这些数字以米为单位。

  4. 测试

    打开您的游戏,在 OBS 或 XSplit 运行的情况下,查看是否排队。 如果没有排队,请关闭您的游戏,然后重试。

故障排除

如果您的系统或游戏滞后,选项包括缩小画布,降低帧速率,使用 GPU 对视频进行编码,或仅在没有流传输的情况下进行录制。 这也可能使事情变得更糟,具体情况取决于游戏和您的系统。 在有这么多不同选项的情况下,提供配置文件似乎不现实。 若要手动更改这些操作,请执行以下操作:

缩小画布

降低帧速率,请谨慎进行,如果帧速率低于 24,则可能会带来更多问题。

使用 GPU 进行渲染

仅录像;不流传输

这篇文章是我作为导师和老师的相关技能的延伸。 通常我可以引导别人顺利过渡到新技术,我非常喜欢与别人分享我的知识。 尽情享受 MR 体验并将反馈发送至:info@undeminerstudios.com

利用英特尔® 数据分析加速库优化线性回归方法

$
0
0

为了提高销量,公司应该如何预测今后在广告中投入的资金总额?同样,为了提高效率,未来公司应该在培训项目方面花费多少资金?

在这两个案例中,两家公司通过不同变量之间的历史关系预测未来的结果,第一个案例中使用的销售额和广告支出之间的关系就是其中一个变量。

这是一个典型的回归问题,机器学习1是解决这个问题的最好方法。

本文描述了一种名为线性回归2的常用回归分析类型,以及英特尔® 数据分析加速库(英特尔® DAAL)3如何帮助优化该算法,使其以更高的性能在搭载英特尔® 至强® 处理器的系统上运行。

什么是线性回归?

线性回归 (LR) 是用于预测分析的最基本的回归类型。LR 展示了变量之间的线性关系以及一个或多个变量对某个变量的影响。受其它变量影响的变量被称为因变量、响应变量或结果变量,影响因变量的变量被称为自变量、解释变量或预测变量。

使用 LR 分析前,需要检查它是否适合该数据集,首先观察数据的分布模式。我们看一下以下两个图表:

Linear Regression Method with Intel® DAAL 1 
图 1:数据点基本沿一条直线分布

Linear Regression Method with Intel® DAAL 2       
图 2:数据点不沿直线分布。

图 1 中的数据点沿一条直线分布;图 2 中的数据点不沿直线分布,而是沿着一条曲线(非线性)分布。因此,可以对图 1 中的数据集进行线性回归分析,但是该方法不适用于图 2 中的数据集。

根据自变量数量的不同,LR 分为两类:一元线性回归 (SLR) 和多元线性回归 (MLR)。

只有一个自变量的 LR 被称为 SLR;MLR 包含一个以上的自变量。

最简单的线性回归只包含一个因变量和一个自变量,它的方程式被定义为:

y = Ax + B      (1)

此处:

y:因变量

x:自变量

A:回归系数或直线斜率

B:常数

问题是如何找到最适合的直线,最大限度地缩减因变量 (y) 的观测值和预测值之间的差异。也就是说,找到方程(1) 中的 A 和 B,计算 |yobserved– ypredicted| 的最小值。

可以利用最小二乘法4找到最适合的直线, 通过计算每个数据点到直线的竖直分异(y 的观察值和预测值之间的差值)的最小平方和,找出最适合的直线。竖直分异也被称为残差。

Linear Regression Method with Intel® DAAL 3
图 3:线性回归图。

图 3 中的绿点代表了实际数据点。黑点表示将数据点竖直(而非垂直)投射至回归线(红线)。黑点也被称为预测点。实际数据点和预测数据点之间的竖直差异被称为残差。

线性回归的应用

以下领域充分了利用线性回归:

  • 预测未来销量
  • 分析营销效果和定价对产品销量的影响。
  • 评估金融服务或保险领域的风险。
  • 根据汽车中的测试数据研究引擎性能。

线性回归的优势和劣势

LR 的某些优势和劣势:

  • 优势
    • 自变量和因变量的关系几乎呈线性时,结果最为准确。
  • 劣势
    • LR 对异常值非常敏感,
    • 不适合模拟非线性关系。
    • 线性回归仅限于预测数值输出。

英特尔® 数据分析加速库

英特尔 DAAL 是一个包含众多优化的基本构建模块的库,适合数据分析和机器学习。这些基本构建模块经过高度优化,能适应最新版英特尔® 处理器的最新特性。LR 是英特尔 DAAL 提供的一种预测算法。在本文中,我们利用英特尔 DAAL 的 Python* API 来构建基本的 LR 预测器。请按照如何在 Linux* 中安装英特尔 DAAL 的 Python版本5中的说明安装 DAAL。

在英特尔数据分析加速库中使用线性回归算法

本节展示了如何利用英特尔 DAAL 在 Python6中调用线性回归方法。

参考部分提供了一个链接7,通过这个链接可以免费获取用于测试应用的数据库。

执行如下步骤,从英特尔 DAAL 中调用该算法:

  1. 利用 from 和 import 命令导入必要的封装。
    1. 执行如下命令以导入 Numpy:
      import numpy as np
    2. 执行如下命令,导入英特尔 DAAL 数值表:
      from daal.data_management import HomogenNumericTable
    3. 导入必要的函数至数值表,以存储数据:
      from daal.data_management import ( DataSourceIface, FileDataSource, HomogenNumericTable, MergeNumericTable, NumericTableIface)
    4. 输入如下命令,导入 LR 算法:
      from daal.algorithms.linear_regression import training, prediction
  2. 如果数据输入来自 .csv 文件,初始化文件数据来源:
    trainDataSet = FileDataSource(
            trainDatasetFileName, DataSourceIface.notAllocateNumericTable,
            DataSourceIface.doDictionaryFromContext
        )
  3. 面向训练数据和因变量创建数值表:
    trainInput = HomogenNumericTable(nIndependentVar, 0, NumericTableIface.notAllocate)
    
    trainDependentVariables = HomogenNumericTable(nDependentVariables, 0, NumericTableIface.notAllocate)
    
    mergedData = MergedNumericTable(trainData, trainDependentVariables)
    
  4. 加载输入数据:
    trainDataSet.loadDataBlock(mergedData)
  5. 创建函数,以训练模型。
    1. 首先利用如下命令创建一个算法对象,以训练模型:
      algorithm = training.Batch_Float64NormEqDense()
      注:该算法利用正规方程解决线性最小二乘法问题。DAAL 还支持 QR 分解。
    2. 输入如下命令,将训练数据集和因变量传输至算法:
      algorithm.input.set(training.data, trainInput)
      algorithm.input.set(training.dependentVariables, trainDependentVariables)
      此处
                algorithm:在上述步骤 a 中定义的算法对象。train
                Input:训练数据。trainDependent
                Variables:训练因变量
    3. 输入如下命令以训练模型:
      trainResult = algorithm.compute()
      此处
                algorithm:在上述步骤 a 中定义的算法对象。
  6. 创建函数以测试模型。
    1. 和上述第 2、3 和 4 步类似,需要创建测试数据集,以进行测试:
      i.
      testDataSet = FileDataSource(
      testDatasetFileName, DataSourceIface.doAllocateNumericTable,
      DataSourceIface.doDictionaryFromContext
       )
      ii.
      testInput = HomogenNumericTable(nIndependentVar, 0, NumericTableIface.notAllocate)
      testTruthValues = HomogenNumericTable(nDependentVariables, 0, NumericTableIface.notAllocate)
      mergedData = MergedNumericTable(testDataSet, testTruthValues)
      iii.
      testDataSet.loadDataBlock(mergedData)
    2. 输入如下命令,创建一个算法对象,以测试/预测模型:
      algorithm = prediction.Batch()
    3. 输入如下命令,将测试数据和训练模型传输到模型:
      algorithm.input.setTable(prediction.data, testInput)
      algorithm.input.setModel(prediction.model, trainResult.get(training.model))
      此处
                algorithm:在上述步骤 a 中定义的算法对象。
                testInput:测试数据。
    4. 输入如下命令以测试/预测模型:
      Prediction = algorithm.compute()

结论

线性回归是一种非常常用的预测算法,英特尔 DAAL 优化了线性回归算法。通过使用英特尔 DAAL,开发人员可充分利用未来更多代英特尔至强处理器的全新特性,无需费心修改他们的应用。他们只需将其应用链接到最新版英特尔 DAAL。

参考资料

  1. 维基百科 – 机器学习
  2. 线性回归
  3. 英特尔数据分析加速库简介
  4. 最小二乘法
  5. 如何在 Linux 中安装英特尔 DAAL 的 Python 版本
  6. Python 网站
  7. 常用数据集列表

面向虚拟现实更新旧版 Unity* 游戏

$
0
0

许多开发人员利用面向 PC 和移动设备的 Unity* 游戏创建了卓越的任务和游戏。  现在,虚拟现实功能已经集成至 Unity 3D,我们需要了解如何更新旧版游戏,以提供出色的虚拟现实体验。本文将向开发人员介绍如何转换现有的 Unity 游戏,使其兼容 HTC Vive* 虚拟现实硬件。

  • 目标虚拟现实类别: 高端虚拟现实
  • 目标虚拟现实硬件: HTC Vive
  • 目标 Unity 版本: Unity 5.0

本文将涵盖以下主题:

  • 重新设计旧版游戏,以提供全新的虚拟现实体验
  • 集成 SteamVR* 插件的技巧
  • 开始使用控制器脚本
  • 全新 C# 到旧版 JavaScript* 解决方案
  • 从 2D 图形用户界面迁移至 3D 用户界面

设计全新的虚拟现实体验

虽然旧版 Unity 游戏并非专为虚拟现实而设计,但是由于 Unity 是一种模拟真实图形和物理的 3D 环境,很有可能您在改善虚拟现实体验方面已经取得了一定的进展。 添加控制器脚本前,您首先需要充分考虑旧版游戏和它所提供的全新的虚拟现实体验。 以下技巧可以帮助您设计适合旧版游戏的虚拟现实体验:

通过设计消除运动眩晕:  标准 Unity 游戏或应用的游戏体验非常令人难忘,但是无法欺骗您的感官, 认识这一点非常重要。 如果您创建了一款非常刺激的高速赛车游戏,然后将它移植到虚拟现实,用户的大脑将会接受非常混乱、错误的信号,最终引起用户的条件反射。 问题是当您的大脑看到虚拟现实世界中的第一人称运动时,它会向您的腿和驱干发送信号,以平衡眼前的运动。 某些用户可能很享受这种游戏体验,但对于大多数用户来说,这是一个非常糟糕的体验,尤其在用户直立时,有可能会摔倒。  如果他们坐着玩游戏,感知到的运动不会造成太大的问题,同时增强了安全性。 评估游戏的最佳体验,考虑建议坐式或站立的游戏体验,以及调整移动,避免用户在场景中遇到平衡问题。

对于站立的玩家,消除运动眩晕的一个有效方法是取消全部的运动,添加远距传动特性,使游戏玩家在空间中随意转换。  借助远距传动特性,您可以以用户的身份站立,将各个方向的移动距离限制在几英尺以内,用户可以将控制器指向游戏中的某个空间,通过远距传动到达那个空间。  例如,如果 FPS 射击玩家借助远距传动特性进行远距离移动,虽然他们只能步行前进或后退几步,但是游戏效果却更好。

我的游戏示例最初设计为第一人称空间驾驶体验。 因此,我决定提供坐式体验,而非空间定位体验, 这样做将不会产生混乱的大脑信号,避免了用户维持双腿平衡的过程中出现双腿僵硬的现象,同时用户能够在场景中自由移动。  我还决定降低多数运动的幅度,使运动缓和了许多。  作为一款空间游戏,实施效果非常不错;在空间中漂浮时,不会因为转弯或运动而感到眩晕。 在坐式体验中,您仍可以感受到运动,但是运动更为可控,不会在大脑中产生杂乱的信号,也无需调整或适应运动。 (如欲进一步迁移至虚拟现实的原始游戏版本,请在查看 本文,这是一篇利用超极本™ 创建 Unity 游戏的教程。) 

面向第一人称设计: 虚拟现实面临的另一个主要问题是第一人称体验。 如果旧版游戏不是专为第一人称视角而设计,需要考虑如何使第三人称视角变为有趣的第一人称体验,或者如何将游戏转换为第一人称视角。

我的游戏属于混合第一人称游戏,但是包含镜头跟随动作的特性。  我认为它太被动,只是间接的第一人称体验。  因此,我决定将人物与动作直接锁定,而非通过脚本间接跟随。

自然交互式用户界面或控制。  由于摄像头的位置不固定,而典型的屏幕菜单在摄像头中显示,因此,交互式用户界面和控制是另一大问题。 摄像头的位置就是用户正在查看的区域。 务必妥善解决控制、菜单和自然交互性问题。  由于多数控制台控制位于游戏手柄,而非屏幕上,因此,控制台游戏开发人员优势非常明显。  如果您设计的移动游戏使用了触摸控制、复杂键或可用鼠标的屏幕控制,您需要重新思考您的控制方案

我的游戏包含了 4 个控制选项:左转、右转、前进和发射。  移动版游戏使用了屏幕可触控控制,PC 版游戏使用了按键命令。  对于虚拟现实版本,我开始借鉴坦克的控制进行设计: 左控制器顺时针旋转,右控制器逆时针旋转等。测试前,这一切似乎比较可行。 我很快发现我的左拇指想要控制两个旋转方向,  事实证明,我之前用游戏手柄玩游戏,无法克服这种肌肉记忆。 HTC Vive 控制器是手持的,手指可以自由放置(和手柄相似),因此,我进行了重新设计。 左控制手柄负责控制方向,右触发器为汽车提供燃料,利用右拇指发射激光,和手柄中的 A 或 X 按钮用法相似。

利用 360 度:  虚拟现实游戏提供 360 度全方位的视角,如果游戏只允许玩家只向前移动,是对虚拟现实优势的一种浪费。  实际上,这是常规版游戏所面临的问题。 我设计了面向所有敌人的迷你-HUD 显示模式,您可以查看敌人是否从两侧或后面靠近您的战舰。  利用虚拟现实技术,只需向左或向右扭头便能轻松观察周围环境。 我将专门针对前进视角以外的危险进行改进,以充分利用 360 度全方位的虚拟现实体验。

针对示例游戏的虚拟现实重新设计决策包含以下几个方面

  • 采用坐姿玩法,以避免眩晕和双腿抽搐的症状
  • 禁用跟踪摄像头,将摄像头锁定车辆的前部
  • 抑制旋转,以避免平衡问题,缓和游戏的移动
  • 将控制映射到 HTC Vive 控制器中,该控制器与手柄控制的布局类似。
  • 创建特性,在更广阔的全景中展示视图和动作

添加 SteamVR 插件

这既不是最简单的操作,也不是最严峻的挑战,  完全取决于代码的老旧程度以及它对 SteamVR 工具套件的兼容。   我将介绍它预期的工作方式以及可能需要您执行的操作。

清理您的游戏,以安装最新版 Unity: 首先,复制原始游戏。 下载最新版 Unity。  打开该版本的旧版游戏。 如有提示,更新 API。  打开游戏并检查控制台是否存在过时的 API,建议您进行更新。

安装 SteamVR 插件: 如果现代版 Unity 能够正常运行游戏,可以下载并导入 SteamVR 插件。 转至 Unity 商店。 搜索 SteamVR 插件, 请选择唯一一个带有熟悉的 Steam 标识的插件。 单击 Import。

选择 All 以导入全部特性、模型和脚本。  所有内容在 SteamVR 文件夹中有序地排列,便于您弄清哪些脚本和资产来自插件。

测试示例场景: 转至下一步之前,确保 HTC Vive 硬件已经连接且正常运行。  在 Unity 中转至 Project 选项卡,打开 SteamVR 文件夹,选择 Scenes 文件夹,然后选择示例场景。  您将看到一个堆着箱子的场景和 SteamVR 截屏。  进入场景并带上头盔。  您应该看到全面的虚拟现实场景以及 HTC Vive 控制器。  如果您看到了上述场景和控制器,可以断定 SteamVR 插件正常运行。

如果没有 – 尝试创建新的项目: 如果您看不到控制器或 SteamVR 示例无法在头盔中加载,需要创建一个新的空白项目。  导入 SteamVR 工具套件并尝试示例场景。 如果这样仍不奏效,表示您的 Unity 版本或 Steam 硬件出现了问题。 

新项目能够正常运行,但是旧项目无法正常运行:  如果全新项目运行良好,但是原始游戏无法兼容 SteamVR 插件,需要再次创建空白项目,安装 SteamVR 工具套件,测试套件是否正常运行,然后将您的游戏迁移至新项目。 为了完成上述操作,首先关闭项目。 在清理后的 Unity 项目中,复制 Assets 文件夹中的全部内容, 转至新项目中的 Asset 文件夹并粘帖。 打开 Unity 项目,开始测试虚拟现实。  这种方法被证实有效。  但是,您的游戏已被损坏,  许多资产的所有项目设置已经丢失,包括从项目组件到游戏资产(如模型、声音文件等)的链接。转至每个资产和每个组件,以确保游戏对象和声音文件正确链接。 这个过程费时费力, 我已经经历过两到三次。 也没有那么糟糕,但是非常琐碎。

更换摄像头:  进行下一步操作之前,请带上 HTC Vive 头盔并正常运行游戏,您应该能够通过转动头部来移动摄像头,还能环顾游戏场景。 但是您仍看不到 HTC Vive 控制器,将虚拟现实应用于摄像头的关键技术还未设置。  下面是实现集成的最关键步骤,  操作起来非常简单,让人难以相信。  为了在应用中添加虚拟现实特性,只需将场景中的主摄像机替换为 SteamVR 文件夹中的 Prefab 摄像头。  就这么简单! 但是,现有摄像头仍有大量的脚本或设置。  不要立即替换摄像头,  建议您以子对象的形式将 Prefab 摄像头放入现有摄像头。  

然后,在现有摄像头的 Properties 面板中关闭摄像头及其全部组件。 在属性面板中,务必取消选中摄像头旁边的选框。

然后,复制粘帖摄像头组件和设置至 Prefab 内的 Camera Head 或 Camera Eye 子对象。 移动、复制并调整设置,戴上 HTC Vive 头盔后,天空盒和其他组件正常运行。

此时,您的旧版游戏已启用了虚拟现实技术。 您应该能够运行该场景,戴上虚拟现实头盔,环顾游戏四周,将看到手上的控制器。 下面介绍如何实现控制器和脚本兼容现有的游戏逻辑。

控制器脚本

如果您和我一样利用 JavaScript 开发游戏,可能会面临更大的挑战,但是不管采用哪种方法,实现控制器脚本与游戏的兼容相当简单。 如果您的游戏中包含 JavaScript,且需要控制器兼容这些脚本,请查看以下章节。  对场景中的左、右控制器进行以下操作。  将控制器(作为子资产)添加到主摄像头下的 Prefab 摄像头中。   Tracked Controller 脚本位于 Extra 文件夹内。  将它拖放到 Camera Prefab 内的控制器(左)中。 控制器(右)和控制器(左)的操作相同。

完成后,在 Inspector 中显示 Trigger Pressed 和其它项目,在游戏中使用这些项目时将进行开关检查。

使用控制器的概念和事件侦听器方法相似。  为了捕获一个事件(如触发或触摸板),需要创建一个 C# 脚本。  以下脚本可以通过许多论坛获取。 在本例中,我向您展示了如何创建事件触发器,以启动触发器、释放触发器、触摸控制器板以及从控制器板上抬起手指。 

C# 脚本在启动触发器或触摸触摸板时触发事件:

using UnityEngine;
using System.Collections;

public class EasyController : MonoBehaviour {
    private SteamVR_TrackedController device;
    void Start () {
        device.TriggerClicked += Trigger
        device.TriggerUnclicked += UnTrigger ;

        device.PadTouched += PadTouch;
        device.PadUntouched += PadLift;
    }


    void Trigger(object sender, ClickedEventArgs e)
        {
//        Place Code Here for Trigger
        }
    void UnTrigger(object sender, ClickedEventArgs e)
    {
 //        Place Code Here for Lifting Trigger
            }

    void PadTouch(object sender, ClickedEventArgs e)
    {
//        Place Code Here for Touching Pad
      }
    void  PadLift(object sender, ClickedEventArgs e)
    {
 //        Place Code Here for UnTouching Pad
    }
}

控制器技巧:  开发游戏时,您会发现无法在虚拟现实中区分左右控制器。  建议在任意控制器上添加一个 3D 资产,如灯、球体或有助于区分左右控制器的任何组件, 以达到开发目的。 稍后,在用户界面章节介绍生成图标和标签的方法,以帮助用户了解如何使用控制器。

此外,可以在除开关以外的其他情况下使用触摸板。  本脚本会根据用户敲击触摸板的位置,支持用户控制游戏。 以下脚本支持您通过敲击触摸板左侧和右侧触发活动。

C# 脚本利用来自虚拟现实触摸板的 X 和 Y 值

using UnityEngine;
using System.Collections;
using Valve.VR;

public class myTouchpad : MonoBehaviour
{
    SteamVR_Controller.Device device;
    SteamVR_TrackedObject controller;

    void Start()
    {
        controller = gameObject.GetComponent<SteamVR_TrackedObject>();
    }

    void Update()
    {
        device = SteamVR_Controller.Input((int)controller.index);
        //If finger is on touchpad

        if (device.GetTouch(SteamVR_Controller.ButtonMask.Touchpad))
        {
            //Read the touchpad values
            touchpad = device.GetAxis(EVRButtonId.k_EButton_SteamVR_Touchpad);
            touchstate = device.GetPress(EVRButtonId.k_EButton_SteamVR_Touchpad);

        if (touchpad.x < 0)
            {
                //  Add code if left side of controller is touched
            }

        if (touchpad.x > 0)
            {
                //  Add code if right side of controller is touched
            }
       }

     else
       {
            // Add code if pad is not touched
        }

    }

}
 

 

C# 和 JavaScript 问题

SteamVR 脚本是以 C# 编写的,导致 HTC Vive 控制器难以甚至无法与现有的 JavaScript 游戏逻辑交互。 利用以下方法可以轻松实现交互,且无需进行转换。  但是,强烈建议您最终将 JavaScript 移植到 C#。

为什么它们彼此缺少交流: 在 Unity 中的脚本存在编译顺序。 可以将 C# 变量迁移至 JavaScript,或者将 JavaScript 迁移至 C# 变量,前提是需要将脚本迁移至 Standard Assets 文件夹。  首先编译这个文件夹,然后应用它们。  但是,由于您需要 JavaScript 来查看 SteamVR 值,Steam 脚本必须位于 Standard Assets 文件夹,且必须第一个进行编译。  如果您移动了它们,会破坏 SteamVR 插件,  因此,无法将 C# 变量传输至 JavaScript。 

但是还有其他方法。

一个简单的变通方法:  我突然想起,C# 和 JavaScript 均可以在游戏对象上接受和设置值。 例如,两种脚本类型均可获得和/或定义该场景游戏对象上的标签值。 游戏对象标签本身就是在脚本之间传输的变量。 例如,如果场景中的 LaserCannon 最初被标记为 “notfired”,触摸板事件可以在 C# 中将 LaserCannon.tag 设置为 “fired”。  现有的 JavaScript 能够查找每帧的对象标签值。 当 LaserCannon.tag = “fired”(由 C# 脚本编写)时,JavaScript 将它们挑选出来,并运行发射激光炮的函数。 这个技巧支持 C# 将事件和值传输至 JavaScript,也支持 JavaScript 传输事件和值至 C#。 

利用上述 C# 示例介绍如何利用 JavaScript 共享变量。 如果我敲击了触摸板的一侧,相应粒子发射器将在 C# 中变更标识值。  打开粒子发射器、播放声音、碰撞检测和相关点的代码全部位于现有的 JavaScript 中,随附于左右粒子发射器。 因此,首先需要在 C# 中明确这些粒子发射器。 将 “rthrust” 和 “thrust” 声明为 GameObjects。 然后在 Start 部分,将对象 “lthrust” 定义为场景中的左粒子发射器,将 “rthrust” 定义为右粒子发射器。  

C# 添加游戏对象至脚本

public class myTouchpad : MonoBehaviour
{
    public GameObject rthrust;
    public GameObject lthrust;

    SteamVR_Controller.Device device;
    SteamVR_TrackedObject controller;


    void Start()
    {
        controller = gameObject.GetComponent<SteamVR_TrackedObject>();
        rthrust = GameObject.Find("PartSysEngineRight");
        lthrust = GameObject.Find("PartSysEngineLeft");
    }

然后,在 If 语句内部(该语句确定触控板的左右侧是否被触碰)添加了代码,以更改标签名称 “lthrust” 和 “rthrust”。 (需要指出的是:您可能认为方向反了,但是在空间中,向右转意味着启动左助推器。)

触摸触摸板时,C# 更改对象的标签值 

if (touchpad.x < 0)
            {
                lthrust.tag = "nolthrust";
                rthrust.tag = "rthrust";
            }

 if (touchpad.x > 0)
            {
                rthrust.tag = "northrust";
                lthrust.tag = "lthrust";
            }

最终,在随附于每个粒子发射器的 JavaScript 中,在 if 语句结尾处添加了一个附加条件"|| this.gameObject.tag='rthrust'",以检查标签是否等于 C# 脚本设置的值。 

JavaScript 基于来自 C# 标签更新执行游戏逻辑

if (Input.GetKey ("left") || this.gameObject.tag=="rthrust"){
         GetComponent.<ParticleSystem>().enableEmission= true;
         GetComponent.<AudioSource>().PlayOneShot(thrustersright);
    }

情况就是如此: C# 和 JavaScript 的交流。  同样的技术可以以相反的方向使用。 这是一个简单的变通解决方案,用于在两个语言和脚本之间启动控制器以及创建基本游戏体验。 完成任务后,建议您将 JavaScript 转换为 C#。

C# 技巧:  如果您刚接触 C#,可以采用以下技巧。  如果对某些数字执行加法、乘法或除法后可能产生小数,需要将变量声明为浮点。  还需要将执行加减乘除运算的数字设置为浮点集。 

  • 声明如下所示:  public float: myVar ;
  • 计算如下所示:myVar = (float)otherVar +1f

将 2D 图形用户界面转换为 3D 用户界面

根据创建 Unity 游戏的年代的不同,您可能使用了图形用户界面菜单、按钮或其他屏幕控制和用户界面元素。 我的旧版游戏专为平板电脑和 PC 而设计,因此包含屏幕和图形用户界面。  在启动菜单、标题图形、屏幕得分和警报中使用了图形用户界面。  头盔中禁用上述功能,但是可以在 PC 屏幕上查看。  在 Google 搜索后发现,需要将图形用户界面转换为用户界面,这是因为用户界面能够在游戏的 3D 空间内显示,支持它们在虚拟现实中可见性与互动性,但是图形用户界面不具备这些特性。

面向虚拟现实的用户界面技巧:用户界面的启用方法非常简单,只需在 Hierarchy 面板中右键单击,添加用户界面并选择 Canvas。  在默认情况下,Canvas 设定为屏幕空间,因此全部尺寸和位置属性在 Inspector 中显示为灰色。  但是在 Properties Inspector 中的 Canvas 模块中,您可以将屏幕视图更改为世界空间。    

更改后,可以在场景中的任何地方对用户界面特性进行放置与排列。  Canvas 设置完成后,可以在 canvas 中添加特定的用户界面项目,如按钮、图像或文本项目。 

为了进行测试,将文本用户界面元素作为子对象添加至 Canvas 项目(请参阅下图左侧)。  在 inspector 的文本输入字段中输入 "Hello World"。  如果您看不到场景中的字,请转至文本的 Properties Inspector。 在 Paragraph 下面,将水平和垂直溢出更改为溢出。 我发现缩放比例有误,默认的字体太大,溢出设置支持您看清文字(甚至在字体过大的情况下)。  您可以利用 Inspector 中缩放特性缩小 Canvas 或文本。  尝试不同的缩放和字体,以确保字体清晰。 如果您的字体边缘是锯齿状,降低缩放并扩大字体。

控制器用户界面:  为控制器提供指令是用户界面的一个绝佳使用案例。  标记左、右控制器,为控制器添加图标,以标记控制器的作用和位置。 左侧是我的启动界面,为每台控制器添加了用户界面,帮助用户辨别左右控制器。 在主游戏场景,控制器配备了图形用户界面,以展示如何操作游戏。

最终,我发现更新游戏并没有那么难,在这一过程中,我思考了如何改进交互,为用户比初始版本更为浸入式、更直观的体验。 仅仅通过练习,我便获取了关于更新原始虚拟现实游戏的更多知识。  请观看以下视频,查看应用虚拟现实技术的游戏示例。

视频地址:https://dn-moderncode.qbox.me/game/updating-older-unity-games-for-vr.mp4

如果您有任何看法或者想和我讨论本次经历,在下方添加评论或通过 Twitter @bobduffy与我联系。


为什么线程在《奇点灰烬》* 中至关重要

$
0
0

 

创建游戏时,您需要不断在特性和性能中作出权衡。 在游戏中添加图形效果和特性时,GPU 是最突出的瓶颈,但是游戏同时也会受到 CPU 的限制。

除了来自游戏逻辑的普通 CPU 负载以外,物理和人工智能 (AI) 计算以及赋予游戏浸入式体验的图形效果也是 CPU 密集型任务,在游戏开发的过程中,GPU 和 CPU 通常交替产生瓶颈。

现代微处理器拥有强大的单核性能,但如果能够充分利用多个 CPU 内核,游戏将能够实现更好的整体性能。 为了充分利用全部的 CPU 计算功能,应用在使用多线程时运行速度最快,此时它们可以确保在所有 CPU 内核上同时运行代码。

视频地址:https://dn-moderncode.qbox.me/game/why-threading-matters-for-ashes-of-the-singularity.mp4

最近,Oxide Games 和 Stardock Entertainment 公司开发了一款实时战略 (RTS) 游戏《奇点灰烬》*,本视频展示的便是这款游戏。 您可以看到在搭载了更多 CPU 内核的系统上,这个游戏如何提供更卓越的游戏体验和性能。

《奇点灰烬》
图 1: 《奇点灰烬》*展示了在搭载了更多 CPU 内核的系统上,高度线程化游戏如何获得更高的帧速率。

Oxide 创建了新的引擎并采用了 Direct3D* 12,如此一来《奇点灰烬》便能利用处理器的所有内核。 该游戏在常见的游戏系统上运行良好,在搭载了更多内核的系统上表现更佳。 您可以在游戏中采用相同的技术,以实现最佳 CPU 性能。

Direct3D* 12 消除了瓶颈并提升了性能。

为了在《奇点灰烬》中获得最快的帧速率,Oxide 团队使用了 Direct3D* 12 版本。 Direct3D 的早期版本运行良好,但是存在几个瓶颈, 在第 12 版中,API 进行了多项变更,消除了影响游戏速度的瓶颈。这些变更包括:多个对象被简化为管线状态对象,更小的硬件抽象层最大限度地降低了 API 开销,从图形驱动程序中消除了资源障碍。

Direct3D 11 能从多个线程中创建命令。 但是,由于旧版 Direct3D 需要大量的串行化,游戏从多线程中获得的加速不多。 通过调整 API,Direct3D 12 彻底消除了这一底层限制。 现在游戏无需使用串行化,便可以使用多个线程填写命令列表,从而显著改善整体线程性能。

通过充分利用这些 API 变更,《奇点灰烬》在 Direct3D 12 上能够实现运行效果。

Nitrous* 引擎使游戏成为可能

Oxide 想要创建一个比以往游戏更复杂的实时战略游戏,支持更大型的军队,拥有更多的单位和更广阔的地图。 为了创建下一代实时战略游戏,开发团队一致认为需要一个新的游戏引擎,现有的游戏引擎无法支持他们期望的单位数量和地图规模。 为了成功开发出《奇点灰烬》,他们从头开始建造 Nitrous 引擎。

任何新的引擎必须首先提供高性能的渲染, 为了达到这个目标,他们对 Nitrous 引擎进行了充分调试,使其支持最新版图形 API、多个 GPU 和异步计算。

游戏为每位玩家提供了多个单位的支持,还提供了大型地图。 在广阔的地形内模拟众多游戏内对象的物理结构生成了庞大的 CPU 负载。 更为重要的是,由于需要模拟每个单位的行为,人工智能工作负载也非常庞大。 游戏支持的大量单位还引发了突发特性。 随着单位数量的增加,玩家直接管理单位的难度不断加大。 Oxide 打造了实现人工智能的分层方法,使军队合理地协作,以利用每个单位的相对优势,同时关注它们的相对劣势。

为了实现这种拓展,Nitrous 将工作分解为更小的任务,实行了引擎的线程化。 任务系统具有较高的灵活性,小型任务可以分散于尽可能多的 CPU 内核中。 由于多数英特尔® 处理器包含英特尔® 超线程 (HT) 技术,Oxide 认真调试了面向速度的任务调度器,调度器在任务之间寻找局部性。 共享已缓存数据的任务在相同物理 CPU 内核中的不同逻辑内核上进行调度,这一方法带来了最佳性能和任务吞吐率。

不论采用何种方法,提升游戏复杂性的过程中总会遇到瓶颈。  开发游戏时,需要考虑预期的相对 CPU 和 GPU 负载。 了解当 GPU 和 CPU 分别成为瓶颈时,游戏将怎样运行。

英特尔® 酷睿™ 处理器为游戏添彩

英特尔® 酷睿™ 处理器能够让您的游戏如《奇点灰烬》般闪耀。 在设计和优化游戏的过程中,您应瞄准中端处理器,并提供扩展到最高端处理的能力。

借助上述技术,《奇点灰烬》在一流的英特尔® 酷睿™ i7-6950X 处理器至尊版上运行良好,这款处理器有 10 个物理 CPU 内核和一个大容量高速缓存,能实现最佳的整体性能。 将工作分解为任务后,借助强大的 GPU,游戏的帧速率随着 CPU 内核数量的增加而提高。 在 CPU 内核数量不同的相同系统上,帧速率稳定增长至最高 10 个物理内核。

该游戏还包括大型地图。 由于玩家和单位数量非常庞大,装备齐全的一组玩家将造成巨大的人工智能负担。 经过认真的调试,《奇点灰烬》借助任务调度器,自动将工作自动分配至全部内核中,只有在 CPU 内核(六个及以上)数量较多的系统中显示地图。 这是一个不错的方法,您也可以效仿:如果您想选择性地启用特性,可以利用 GetsystemInfo() 等函数检测系统的内核数量。

可扩展效果使游戏更胜一筹

尽管游戏主要关注如何在内核数量较多的系统上提升帧速率,但是仍可以利用一小部分 CPU 空间为玩家带来惊喜。 随着内核数量的增多,《奇点灰烬》将在某些单位内自动启用高级粒子效果,还会启用临时运动模糊。

《奇点灰烬》
图 2: 两个大型战舰单元上的高级粒子效果看起来非常炫酷。

这些粒子效果带来了更强烈的视觉震撼,但是不影响游戏进程。

《奇点灰烬》
图 3: 临时运动模糊增强了迅速移动单位的真实感。

临时运动模糊在多个帧内模拟快速移动单元,然后将它们合成为一张模糊的帧,增强了单元的真实感。

仔细查看,然后创建您自己的炫酷游戏!

《奇点灰烬》提供了极佳的性能,随着 CPU 内核数量的增多,性能还会进一步扩展。 借助最新版 Direct3D API 实现了上述性能提升,Direct3D API 支持多线程和更高效的任分区与调度,能够主动检测内核可用性,以启用更复杂的特性。 更多的内核数量将解锁更复杂的游戏内容和更广阔的地图。 临时运动模糊和增强的粒子效果造就了炫目的游戏。 最新发布的更新版《Ashes of the Singularity: Escalation》基于上述优势而创建,添加了更大的地图,改进了用户界面,在不同的平台上提供更出色的性能。

希望您能从中获得灵感,将这些设计原则应用到您的开发项目中,创建一款炫酷的游戏!

图形调试? 从英特尔® 图形性能分析器开始着手

图形优化本身是一个宽泛的话题。 推荐您使用英特尔® 图形性能分析器开始调试游戏。 访问 https://software.intel.com/zh-cn/gpa了解这些工具。

英特尔® Nervana™ 人工智能研究院大学研讨会和讨论会

$
0
0

2017 年,英特尔® Nervana™ 人工智能研究院学生开发人员计划吸引了全球众多大学的参与,在大学校园内举办了多场技术研讨会和讨论会。我们真诚邀请来自各个专业、社团和拥有各种兴趣爱好的学生参加大会并了解英特尔在机器学习、深度学习和人工智能领域所取得的进展。教职工和学生 还可以参与并展示他们在各自领域内的研究成果和专业知识,英特尔也展示了在英特尔® 架构上运行的最新版工具、技术和计划,为人工智能带来强大的支持。

目前,这些研讨会在美国、非洲、印度、中国和欧洲举办。每一场研讨会都会根据学生的需求和兴趣进行调整,但是多数研讨会在开场时,由英特尔成员或嘉宾主持简要介绍技术议程,以及学生如何推动英特尔的发展。

英特尔® 学生开发人员人工智能研讨会 - 加州大学 (UC) 克利分校专场

在活动中,英特尔介绍了为学生提供的技术和计划,包括:

  • 全体参会学生均可获取的技术,如远程访问运行英特尔® 优化库和框架的英特尔® 服务器。

  • 从收集、分享和讨论人工智能知识的学生社团中挑选优秀的社团并颁发赞助。

  • 英特尔学生校园大使计划,为优秀学生提供英特尔支持,并协助宣传他们在英特尔架构上支持人工智能的项目。

上图 显示了面向英特尔架构优化的各项技术,从英特尔® CPU 到库,如英特尔® 数学核心函数库(英特尔® MKL)和面向深度神经网络的英特尔® 数学核心函数库(英特尔® MKL-DNN)。深度学习框架是新兴的人工智能解决方案的核心,英特尔正积极完善每一个主要框架,以面向英特尔架构优化这些主要框架。框内的部分展示了学生开发人员计划提供的技术,学生可以立即获取、免费试用这些技术。此外,从众多申请者中挑选出的学生校园大使在参与计划期间,有权利访问基于最新版英特尔® 至强融核™ 处理器的服务器,还能访问特定的工具。了解关于 学生校园大使计划的更多信息。

面向人工智能的欢迎和议程概述示例 - 加州大学伯克利分校学生研讨会

技术课程:研讨会至少提供两门技术课程,一般会根据大学的需求、课程或重点而调整,可能包含:

  • 机器学习和深度学习简介

  • 从技术层面深入探讨深度学习

  • 英特尔® 深度学习 SDK 演示/培训

  • 面向英特尔架构而优化的 Caffe* 演示/培训

  • 采用英特尔® Nervanad 技术和 Neon 框架的深度学习简介

  • 采用英特尔® Nervanad 技术和 Neon 框架的演示/培训

  • 从事机器学习、深度学习和人工智能研究的教职工或学生

示例课程:

采用英特尔® Nervanad™ 技术和 Neon 框架的深度学习简介

应用 Neon 框架的英特尔 Nervana 技术平台的深度学习演示

使用深度学习方法进行 MOOC 行为建模的学生课程

获取关于英特尔 Nervana 人工智能研究院的更多信息。了解关于如何申请 面向人工智能的英特尔学生校园大使计划的更多信息。

NetUP 利用英特尔® 媒体软件开发套件向全球数百万观众转播里约奥运会赛事

$
0
0

2016 年 8 月,全球各地的 50 万粉丝来到里约热内卢,观看为期 17 天的夏季奥运会。 同时,全球数百万观众在电视机屏幕前观看了奥运会直播。

在不同的大陆上进行实况电视转播是一项艰巨的任务,需要可靠的设备和灵活的技术支持。 对全球最大的多媒体新闻机构 - 汤森路透 (Thomson Reuters) 来说,这是个不小的挑战。

为了迎接挑战,汤森路透选择了 NetUP 作为技术合作伙伴,使用 NetUP 设备进行了从里约热内卢到纽约与伦敦办事处的实况转播。 NetUP 与英特尔携手开发了 NetUP 转码器,使用了英特尔® 媒体软件开发套件,该套件是一款跨平台的 API,用于在 Windows* 上开发媒体应用。

”这个项目对我们来说非常重要,“ NetUP 创始人 Abylay Ospan 说,”它展示了我们开发的解决方案的高品质和可靠性,可以用于转播全球盛事,如奥运会。 英特尔媒体软件开发套件支持快速转码,确保全球观众都能够收看奥运会转播。“

请访问最新的案例研究以了解全部详情。

快速的 ISPC 纹理压缩工具 - 更新

$
0
0

下载代码示例

本文和示例代码项目由英特尔公司的 Marc Fauconneau Dufresne 撰写。

2016 年 4 月 12 日更新
本次更新添加了面向 RGBA ASTC 压缩的支持。

2015 年 8 月 26 日更新
本次更新在快速的 ISPC 纹理压缩示例中添加了高质量的 ETC1 和 ASTC 压缩。对于 ASTC 压缩,目前只支持 RGB 2D LDR 输入。支持最高 8x8 的模块规格(而非 10x5 或 10x6)。利用 英特尔 SPMD 编译器启用 SIMD 指令集。下图展示了在带有 6x6 模块的 Kodak 数据集上,astcenc 与快速 ISPC 纹理压缩工具的性能与质量关系的对比。在快速预置方面与 astcenc 不相上下,但是速度提升了 44 倍。


图 1 - 快速 ISPC 纹理压缩工具与 astcenc 之间的性能与质量对比需要注意的是,x 轴运用了对数尺度。

 

2014 年 5 月 13 日更新
本示例在 一流的 BC7 纹理压缩工具上 添加了 BC6H(DX11 HDR 纹理格式)支持。我们采用了相似的方法进行快速分区过滤、选择和修改,还采用了高效的搜索策略,以充分利用 B6CH 端点转换。利用 英特尔 SPMD 编译器启用了 SIMD 指令集。提供了质量与性能之间的各种关系。


图 2ISPC 纹理压缩工具更新 - 2014 年 5 月 13 日

原始版本(2013 年 11 月 5 日)
本示例展示了一流的 BC7 (DX11) 纹理压缩工具。BC7 分区被简化为若干阶段,利用迭代端点修改优化了最终的分区。支持所有 BC7 模式。借助 英特尔 SPMD 编译器启用了 SIMD 指令集。提供了质量与性能之间的各种关系。


图 3 - 原始 ISPC 纹理压缩工具 - 2013 年 11 月 5 日

Docker* 容器中大数据工作负载的裸机性能

$
0
0

BlueData® 和英特尔® 密切协作,史无前例地推出了一套面向大数据工作负载的性能指标。分别在裸机环境中和基于容器的环境(使用 BlueData EPIC™ 软件平台)中对这些工作负载进行性能指标评测。两种测试环境的工作负载在基于英特尔® 至强® 的架构上运行同等配置。

这篇深入研究显示,BlueData EPIC 平台上的基于容器的  Apache Hadoop* 工作负载在性能上与裸机 Hadoop 不相上下,在某些情况下会更高。例如,性能指标评测显示,与裸机相比,BlueData EPIC 平台的性能平均提升了 2.33%,该平台配置了 50 个 Hadoop 计算节点和 10 TB 数据。

上述结果表明,您可以利用 BlueData 所具有的敏捷性、灵活性和低成本等优势,同时在 Docker* 容器中运行大数据工作负载,还可以进一步提升裸机环境中的性能。

设备端 AVC 运动评估简介

$
0
0

下载示例

下载设备端 VME 示例代码 和高级示例

运行指令详见 VME 示例用户指南。 请参阅 AVC 设备端 VME 手册

请注意:本示例目前仅限在 Linux*、SRB4/Media Server Studio 2017 R2 及更高版本中运行,仅支持第六代智能英特尔® 酷睿™ 处理器及更新一代的处理器。

简介

本文介绍了面向 OpenCL* 的全新设备端 h.264/高级视频编码 (AVC) 运动评估扩展,该扩展由英特尔处理器图形 GPU 提供;视频运动评估 (VME) 硬件作为英特尔® 媒体软件开发套件视频编解码器的重要组件,多年前便可以进行访问,也可以通过主机调用的内置函数进行访问。全新   cl_intel_device_side_avc_motion_estimation扩展(在 Linux 驱动程序 SRB4 中获取) 提供了从内核访问硬件支持 AVC VME 功能的细化接口。 

以下部分介绍了 VME 如何利用英特尔扩展访问 OpenCL* 标准:

运动评估概述

运动评估流程可以用于搜索一系列本地(数据块级别)转换,这些转换能够出色地匹配帧和帧之间的时间差异。 如果没有硬件加速,该搜索成本高昂。 通过实现该操作的硬件加速,我们能够以全新的方式对各种算法进行研究。 

 对于第六代酷睿/Skylake 处理器,英特尔® 处理器显卡 Gen9 计算架构 指南提供了 更多的硬件信息, 可以简要概括为:

  • VME 硬件作为采样器模块的一部分,包含在所有子切片中(下图左下方)。英特尔分支团体在子切片级别工作,设备端 VME 扩展也基于分支团体。
  • Gen9 硬件的每个切片一般包含 3 个子切片(24 EU/片)。
  • 处理器包含的切片数量各不相同,  您可以根据 ark.intel.com(提供处理器图形 GPU 的名称)或 notebookcheck.com 等其他网站(提供关于处理器图形模型的更多信息)中的信息确定切片的数量。

运动搜索是许多现代编解码器的核心操作, 它还有许多其它方面的应用。 可以添加至视频稳定和帧插值等过滤器中,以进行视频处理。 它还是一款实用的预处理器,可以进行编码,提供运动复杂性、运动在帧中的位置等信息。   

从计算机视觉的角度看,运动矢量是基于光流的算法基础。

目前可用的英特尔® 处理器图形 GPU 硬件只支持 AVC/H.264 运动评估, HEVC/H.265 运动评估要复杂得多。 但是,这不一定意味着 AVC 运动评估只面向 AVC。 可以利用 VME 返回的选择(旨在简化 AVC 运动方向搜索)  缩小第二次通过/更详细的搜索(如需要)的搜索区域。

 

设备端接口

之前的实施注重主机调用的内置函数, 设备端实施需要若干设置阶段的内核代码:

  1. 一般初始化 (intel_sub_group_avc_ime_initialize)
  2. 操作配置(包括内部成本及所需的其他属性)

(来自 vme_basic.cl)

      intel_sub_group_avc_ime_payload_t payload =
        intel_sub_group_avc_ime_initialize( srcCoord, partition_mask, sad_adjustment);

      payload = intel_sub_group_avc_ime_set_single_reference(
        refCoord, CLK_AVC_ME_SEARCH_WINDOW_EXHAUSTIVE_INTEL, payload);

      ulong cost_center = 0;
      uint2 packed_cost_table = intel_sub_group_avc_mce_get_default_medium_penalty_cost_table();
      uchar search_cost_precision = CLK_AVC_ME_COST_PRECISION_QPEL_INTEL;
      payload = intel_sub_group_avc_ime_set_motion_vector_cost_function( cost_center, packed_cost_table, search_cost_precision, payload );

然后是评估阶段 (intel_sub_group_avc_ime_evaluate*). 随后可以利用 intel_sub_group_avc_ime_get* 函数提取结果。

      intel_sub_group_avc_ime_result_t result =
         intel_sub_group_avc_ime_evaluate_with_single_reference(
             srcImg, refImg, vme_samp, payload );

      // Process Results
      long mvs           = intel_sub_group_avc_ime_get_motion_vectors( result );
      ushort sads        = intel_sub_group_avc_ime_get_inter_distortions( result );
      uchar major_shape  = intel_sub_group_avc_ime_get_inter_major_shape( result );
      uchar minor_shapes = intel_sub_group_avc_ime_get_inter_minor_shapes( result );
      uchar2 shapes = { major_shape, minor_shapes };
      uchar directions   = intel_sub_group_avc_ime_get_inter_directions( result );

 

在本示例中,我们利用相似的步骤修改了运动评估的子像素:

     intel_sub_group_avc_ref_payload_t payload =
       intel_sub_group_avc_fme_initialize(
          srcCoord, mvs, major_shape, minor_shapes,
          directions, pixel_mode, sad_adjustment);

     payload =
      intel_sub_group_avc_ref_set_motion_vector_cost_function(
         cost_center,packed_cost_table,search_cost_precision,payload );

     intel_sub_group_avc_ref_result_t result =
      intel_sub_group_avc_ref_evaluate_with_single_reference(
         srcImg, refImg, vme_samp, payload );

     mvs = intel_sub_group_avc_ref_get_motion_vectors( result );
     sads = intel_sub_group_avc_ref_get_inter_distortions( result );

 

预期结果

请注意 --  下面仅用了输入/输出帧的 一小片区域。

来自输入(源帧和参考帧/前一帧)

本示例的测试片段中产生了“缩小”的运动, 下图显示了主要差异的位置(来自源图像和参考图像的 imagemagick 对比)。

此处显示示例的输出覆盖了运动矢量。 需要指出的是,多数符合缩小的预期径向模式。

其他输出包括 AVC 宏模块形状选择(如下所示)和残差。

结论

视频运动评估是一个强大的特性,开启了探索用于视频编解码器和计算机视觉的众多算法的全新方式。 如果在 CPU 上搜索最具代表性的运动矢量,会产生高昂的计算成本, 可以将搜索卸载至英特尔处理器图形架构图像采样器中的特定硬件。 全新的设备端(从内核中调用)接口支持更高的灵活性和定制功能,同时减少主机端启动的潜在性能成本。

参考资料

 

 

如欲获取关于编译器优化的完整信息,请查看 优化通知

OpenCL 和 OpenCL 标识是苹果公司的商标,需获得 Khronos 的许可方能使用。

 

3D 同性声波有限差分波动方程代码:多核处理器实施与分析

$
0
0

有限差分是一个简单有效的数学工具,用于求解微分方程。在本文中,我们将利用明确的时间域有限差分求解同性声波 3D 波动方程。

即使使用最简单的波动方程表达式,传播地震波仍是一个计算密集型任务。在本文中,我们将介绍如何部署并优化采用有限差分的三维同性内核,以便在英特尔® 至强® 处理器 v4 产品家族和英特尔® 至强融核™ 处理器上运行。

还将简要介绍与英特尔® 至强融核™ 处理器一同推出的新内存层次结构,以及对源代码的各种设置和修改,这些源代码是在多通道 DRAM (MCDRAM) 上面向动态存储分配集成 C/C++ 高带宽内存 (HBM) 应用编程接口 (API) 的使用所必需的。


利用最新款 CPU 创建沉浸式虚拟世界

$
0
0

作者:Justin Link
(Chronosapien 公司)

三年多以来,我经营了一家名为 Chronosapien 的工作室,我们专门利用新兴的技术组件创建交互式内容。 我们采用了多种技术,但是最令我们感兴趣的是虚拟现实技术,因此,我们开始创建我们自己的项目,项目名称为 Shapesong*。

无论从哪个方面来看,从事 Shapesong 项目都是一段特别的经历。 最有趣的地方在于学习如何实现系统的最佳性能,同时始终适应不断变化、日趋成熟的媒体。 本文介绍了我们在创建可信的、极具吸引力的虚拟现实环境中获得的经验,以及如何通过硬件(主要针对 CPU)实现虚拟现实。

新的预期

2016 年第一代设备浪潮的来临使许多人初次体验了虚拟现实。 由于虚拟现实是一个强大的自然用户界面,人们进入虚拟现实界面的方式和传统媒体设备界面的方式完全不同。 用户希望虚拟现实提供流畅自然的内容和体验。 例如,如果一个从未尝试过虚拟现实技术的人戴上虚拟现实设备,他首先会问:“我的手在哪里?”,而不是问该按哪个按钮。 将用户置于虚拟现实环境中,他们做的第一件事不是询问该干什么,而是立即开始触摸物体,捡起来再扔下,还进行了其他交互,您可能不会料到使用电脑程序的用户会产生这样的行为。

当期望落空时,心中的疑虑被打破,虚拟现实的错觉也随之消失。 用户不再处于虚拟现实世界中,他们透过镜头看到了数字副本,包含了毫不掩饰的设计元素和设定的场景。

许多虚拟现实使用案例不包括创建虚拟环境。 然而,由于虚拟现实应用的目标是沉浸与传输,开发人员和设计人员的必须创建栩栩如生的世界,为用户提供和真实世界一致的响应。 这意味着创建可以变化与恢复的环境,可以捡起与扔掉的物体以及可以塑造与修改的工具。

这便是下一代交互式体验的目标,创建一个栩栩如生的虚拟现实世界。 用户通常希望虚拟现实的交互方式与真实世界的交互方式相同,但是他们无法看到沉浸式和交互性体验所隐含的计算。 开发人员利用现有的技术和工具为虚拟现实环境添加生动、逼真的效果,但是他们能做的只有这些。 在某些情况下,为了支持这些体验,他们需要利用性能更强大的硬件,

这是我和我的团队所面临的挑战。 开发我们自己的虚拟现实体验 - Shapesong 时,我们掌握了增强沉浸式效果需要创建的组件,也了解了创建的方法。 交互性和沉浸式体验的宽度非常广泛,传统系统的计算资源又非常有限,我们不得不选择部分区域进行创建,或增强创建流程的创新性。 很像用一根吸管吸一座山。

在本文中,我将介绍 Shapesong 消耗 CPU 性能的几个途径,它对用户的影响以及更强大的 CPU 对扩展沉浸式体验的支持。 我的目标是帮助人们更好地了解高端虚拟现实系统在支持沉浸式虚拟体验方面的优势。

什么是 Shapesong?

首先,我们来了解 Shapesong 的环境。 Shapesong 是面向下一代音乐交互式体验的解决方案。 用户能探索音乐环境、发现用于虚拟乐器的声音、在提供伴舞和娱乐的场景中创造音乐,还能与自己的克隆或其他人共同弹奏音乐。 简而言之,Shapesong 就是一个《幻想曲》《欢乐糖果屋》在共享的虚拟世界中相遇的体验。 下面是我们的概念验证演示视频:

视频地址:https://dn-moderncode.qbox.me/game/shapesong-proof-of-concept-teaser.mp4

Shapesong 预告片。

我们的目标是创建一个随时随地弹奏音乐的世界,为用户提供工具,使他们利用环境和找到的乐器来创造音乐。 我们还尝试创造一种将视觉和音乐表演融合在一起的联觉体验,使演奏者和观众完全沉浸其中。

我们需要实时设计与控制该体验的许多方面,因此,运行 Shapesong 的系统功能变得尤为重要。

创建一个音乐世界

虚拟实行严格的每秒 90 帧的渲染时间,每帧约 11 毫秒。 相比之下,传统体验的渲染时间为每秒 30 帧,即使某些区域低于每秒 30 帧也不会产生重大后果,虚拟现实则不然。 实际上,虚拟现实需要渲染场景的两个版本,每只眼睛对应一个版本。 这意味着虚拟现实的渲染负载是平面媒体设备的两倍。 这些规则存在一些例外,也可以利用技巧改变规则,但是最重要的是,虚拟现实对计算的要求要严格得多,成本也高了一大截。

Shapesong 实现了一些独特特性,对虚拟现实系统的性能提出了更高的要求。 从技术的角度来看,Shapesong 是数字音频工作站 (DAW) 和视频游戏在虚拟环境中的结合。 上述三个部分均能消耗大量的 CPU 周期。 我们看一下 Shapesong 中完全依赖 CPU 性能的领域。

音频处理

作为一款音乐游戏,Shapesong 处理了大量音频,这点不足为奇。 除了对环境、玩家和用户界面声音进行基准渲染以外,还需要渲染不同时期的乐器演奏。 事实上,多个乐器的平均音频处理负载是基准(只演奏一件乐器时)的 20 倍。


图 1:在 Shapesong 中弹奏键盘

这是乐器的幕后原理。 如果您想在乐器上弹奏一个音或音符,需要播放该音符的音频剪辑。 从某些方面来说,一架全尺寸钢琴有 88 个琴键/音符,可以在特定时间内弹奏。 在 Shapesong 中弹奏相似的虚拟乐器时,最多可以同时播放 88 个不同的音频剪辑。 前提是假设每个音符只能同时弹奏一个活动音符或声音,但是,在 Shapesong 中情况并非总是如此。

除了基于音频的乐器演奏方法外,还有另一种方法—声音合成。 但是,声音合成不能代替示例,它拥有独特的处理开销。 我们希望 Shapesong 支持两种方法,在弹奏音乐时实现最大的灵活性。

环境影响

正如我刚才说的,我们希望在 Shapesong 中实现视觉和音乐表演的结合,以创造全新的音乐体验。 播放的音乐需要与环境中的视觉效果保持同步。

多数人认为游戏或体验中的任何图形都是由图形显卡或 GPU 渲染的。 实际上,CPU 执行绘制调用,在图形渲染管线中发挥重要的作用。 绘制调用本质上是 CPU 确定图形任务并将其发送到 GPU 的过程。 总体来说,当存在需要绘制到屏幕的独特任务时,执行绘制调用。

在 Unity* 中,批量处理流程对 Shapesong 引擎和绘制调用进行优化。 批量处理收集相似的绘制调用,将它们聚集到单个调用中,然后发送到 GPU,极大节省了计算时间。 然而,只有在特定条件下 Unity 才执行批量处理,其中一个条件是全部对象共享相同的材料。 另一个条件是批量处理对象必须全部静止,不得改变位置或以任何方式运动。 对于静态环境(如共享相同材料的 200 棵树)而言,批量处理效果非常出色。 但是,如果您想要每一颗树对玩家输入或音乐演奏产生独特的响应时,批量处理不起作用。

无论虚拟世界是否需要响应音乐,该条件为创建栩栩如生的虚拟世界带来了巨大的挑战。 如果无法移动或修改某个场景中的物品,如何使该场景变得栩栩如生? 现实情况是:您需要挑选进行生动展示的部分,并以创新的方式添加效果,这是游戏开发普遍面临的一个长期问题。 如上所述,传统体验和下一代体验的区别在于用户的期待。

物理对象

增强虚拟世界的逼真度不仅需要在环境中添加动画, 还要根据现实世界中习以为常的物理定律设计动画。 事实上,您甚至可以认为当前的虚拟现实系统不是真正的虚拟现实系统,只是叠加了虚拟世界的增强虚拟(参阅混合现实)。 为什么? 因为尽管在虚拟现实中看到了虚拟环境,我们依然站在物理世界中,物理世界受所有自然规律的控制。 重要的是如果您想创建一个无缝的自然体验,不想破坏这个假象,需要将物理实体的定律应用到虚拟现实中。


图 2: 丢掉声筒。

我们想在 Shapesong 中创建一个自然的环境,用户可以利用环境中的物体进行演奏,探索音乐环境。 例如,我们希望用户能捡起一块石头,然后在池塘的水面上打水漂,当石头滑过水面时会播放音符,用户也可以扔球,听球下落时音高的变化。 目的是鼓励非专业人士进行音乐探索,消除他们对音乐的畏惧心理。

游戏引擎中的物理机制没有那么难启动,但是成本极其高昂,也非常耗费 CPU 资源。 物理系统不仅需要逐帧计算受物理约束的对象的新位置,还要检查对象和其他环境的接触。 随着物理生成的对象数量和接触它们的对象数量的增长,成本也随之上涨。

录制演奏

用户录制游戏的方式使 Shapesong 变得独一无二。 我们希望充分利用虚拟现实功能和支持虚拟现实的系统,同时录制演奏。 过去,DAW 录制音乐时,只收集弹奏的音符,不会捕捉手掠过琴键的动作,也不会捕捉沉浸于节奏时头部的摆动。 但是音乐不仅在于弹奏的音符, 弹奏的方式也是音乐的重要组成部分。


图 3: 和您的克隆一同弹奏

我们记录了用户的全部输入,将它们制作成一段动画,通过虚拟的人物进行回放。 用户录制演奏本质上是为了克隆自己的在某段时间内的活动。 当玩家弹奏乐器时,克隆玩家的音乐演奏。 当玩家位于其他地方时,克隆玩家与环境的互动、舞蹈或者仅仅是打招呼。

录制一场演奏不会消耗太多资源,但是回放演奏却能消耗大量资源,尤其在演奏规模扩大时。 例如,一首歌的某一节同时弹奏了 4 或 5 种乐器:节奏、低音、旋律、弦乐器和纹理。 可能还包括了一些视觉表演,如跳舞、绘制发光的拖尾或触发环境中的对象。 因此,在典型环境中,用户可能随时播放 10 个或以上录制。 每一个角色包含 3 个记录位置的对象:左手、右手和头部。 我们还跟踪保存的对象角色以及这些对象的状态。 在典型环境中,回放的对象或属性总计至少 100 个,每帧都会对它们进行全部处理。

更强大的硬件性能将带来怎样的变化?

很明显,虚拟现实提出了严格的性能要求, 模拟沉浸式环境和支持它们的功能可能花费高额成本,这也是可以理解的。 那么这意味着什么? 这些 CPU 性能要求对虚拟现实的最终体验产生了怎样的影响?

处理能力增强通常会导致虚拟环境规模的扩大,这是处理能力增强的一个主要影响。 之前发布的体验几乎全部存在于小房间或气泡内,交互性非常有限。 例如,《Tilt Brush*》限制环境画布的规模,最近才支持用户走出空间定位的范围。 《Lab*》创建于实验室内部,实际上只有几个空间定位大小。 即使看起来更为开放的环境(如《Lucky’s Tale*》中的环境)也赶不上同类的现代平台游戏,如《超级马里奥星河*》。 由于 CPU 提供了更卓越的性能,我们将进一步扩大环境,创建并探索更加无缝、多样的世界。

处理能力对虚拟现实体验的另一个影响是有限的交互性。 之前发布的多数体验注重某一类交互性,然后对其进行扩展。 例如,《Job Simulator*》是一个物理沙盒,支持用户捡起、扔掉对象,或以独特、有趣的方式混合使用对象。 《Raw Data*》属于大规模射击游戏,系统可生成成群的敌人供用户射击。 《Audio Shield*》动态生成球体,玩家利用盾牌抵挡球体,与歌曲的节拍保持同步。 尽管这些游戏都很出色,也非常好玩,但是体验的深度相对较浅,因此,其吸引力远不及其他常见的非虚拟现实游戏。 更强的处理能力能减轻每个交互系统的硬件压力,有助于提升交互性的宽度和深度。 《亚利桑那阳光》在原有的多人射击体验的基础上,利用高性能 CPU 启用了许多物理对象和僵尸。

这些效果正是 Shapesong 提供的体验。 随着支持特性的增多,必须缩小环境边缘。 添加了更多的角色意味着必须限制主动音频语音的总数。 我们利用音乐启用了更多视觉效果,必须降低其它地方的图形逼真度。 这些妥协并非仅限于虚拟现实,它们一直存在于各种游戏或体验中。 不同之处在于现实的预期,用户总是提出详细的要求,虚拟现实系统的要求至少比传统系统严苛两倍。 提升虚拟现实系统中的 CPU 性能,有助于创建沉浸式和完全透明的虚拟世界。

展望未来

借助虚拟现实,我们处于媒体领域新标志性转变的前沿。 我们直接进入了人们的想象深处,而不是在外面驻足观望,我们现在可以与世界和角色进行生动、逼真的交互。 这是一个新型的目标,在我们定义下一代虚拟体验之前,需要重新考虑实现这一体验的技术。 宇航员不会坐着缓慢前进的飞行器到达月球,我们也不会借助浏览网页的 PC 探索虚拟现实世界。

但是实现虚拟现实体验不能只依赖最新的计算技术, 还需要我们对现实世界进行模仿,设计沉浸式体验的效果,同时需要打破现实,以便退出。 对于开发 Shapesong 的开发人员来说,这意味着在创建的环境中应用类似于现实世界的全新物理法则,利用直观、独特的交互式方法进行音乐创造。 当然,全新的虚拟现实体验都有其独特的风格,突破了某些限制,但是全部依靠技术来实现。

如何在英特尔® 至强融核™ 处理器中使用 MPI-3 共享内存

$
0
0

本白皮书简要介绍了 MPI-3 共享内存的特性、相应的 API 和一个示例程序,以展示如何在英特尔® 至强融核™ 处理器中使用 MPI-3 共享内存。

MPI-3 共享内存简介

MPI-3 共享内存是消息传递接口 (MPI) 标准版 3.0 的一个特性,实施于英特尔® MPI 库 5.0.2 版及更高版本。MPI-3 共享内存支持多个 MPI 进程,以分配并访问计算节点内的共享内存。对于需要多个 MPI 进程的应用(以交换海量本地数据)而言,该特性减少了内存空间,能够显著提升性能。

在 MPI 标准中,每个 MPI 进程都有各自的地址空间。借助 MPI-3 共享内存,每个 MPI 进程都面向其它进程公开了内存。下图展示了共享内存的概念:每个 MPI 进程分配并维持自己的本地内存,并在共享内存区域显示部分内存。因此,所有进程均可访问共享内存区域。利用共享内存特性可以减少进程中的数据交换。

Data exchange among the processes

在默认情况下,单个 MPI 进程创建的内存为私有。只共享内存,其他资源仍需保密时,最好使用 MPI-3 共享内存。由于每个进程均可访问共享内存区域,用户使用共享内存时,需要注意进程同步。

示例代码

本部分提供了示例代码,以展示 MPI-3 共享内存的应用。

该节点总共生成了 8 个 MPI 进程。每个进程都维护了一个由 3200 万个元素构成的长数组。对于数组中的每个元素 j,进程基于它的当前值和两个相邻进程中相应数组的元素 j值更新该元素值,并在整个数组中重复应用相同的程序。以下伪代码显示了 8 个 MPI 进程(64 次迭代)运行该程序:

Repeat the following procedure 64 times:
for each MPI process n from 0 to 7:
    for each element j in the array A[k]:An[j] ← 0.5*An[j]  + 0.25*Aprevious[j] + 0.25*Anext[j]

An 是一个长数组,属于进程 nAn [j] 是数组中元素 j 的值,属于进程 n。在本程序中,由于每个进程在本地内存中显示了内存,因此,尽管每个进程只需要两个相邻的数组(例如,进程 0 需要来自进程 1 和进程 7 的数据,进程 1 需要来自进程 0 和进程 2 的数据),所有进程均可访问全部数组。

Shared Memory Diagram

除了用于 MPI 编程的基本 API 以外,本示例还介绍了以下 MPI-3 共享内存 API:

  • MPI_Comm_split_type:用于创建一个新的通信器,使全部进程共享一个通用属性。在本示例中,为了从母通信器中创建一个共享内存(如 MPI_COMM_WORLD),将 MPI_COMM_TYPE_SHARED传递为变量,然后将通信器分解为共享内存通信器 shmcomm
  • MPI_Win_allocate_shared:用于创建一个共享内存,所有进程均可在共享内存通信器中访问该共享内存。每个进程向其他所有进程显示了其本地内存,每个进程分配的本地内存大小可能有所不同。在默认情况下,连续分配总体共享内存。用户可以传递一条信息提示“alloc_shared_noncontig”,以指明不需要连续分配共享内存,这样可能会提升性能,提升与否取决于基础硬件架构。 
  • MPI_Win_free:用于释放内存。
  • MPI_Win_shared_query:用于查询 MPI 进程的共享内存地址。
  • MPI_Win_lock_allMPI_Win_unlock_all:用于启动窗口中所有进程的访问 epoch。仅需共享 epoch。调用进程可以访问所有进程的共享内存。
  • MPI_Win_sync:用于确保复制本地内存到共享内存的操作已完成。
  • MPI_Barrier:在所有进程到达 barrier 前,拦截节点上的调用者进程。barrier 同步 API 在所有进程上运行。

对英特尔® 至强融核™ 处理器进行基本性能调试

本测试在英特尔至强融核处理器 7250(1.40 GHz、68 核)上运行,该处理器安装了 Red Hat Enterprise Linux* 7.2、英特尔® 至强融核™ 处理器软件 1.5.1 和 英特尔® Parallel Studio 2017 更新 2。在默认情况下,英特尔编译器尝试对代码进行矢量化处理,每个 MPI 进程都有一个执行线程。OpenMP* pragma 被添加到循环层面,便于随后使用。为了编译代码,运行以下命令行以生成二进制 mpishared.out

$ mpiicc mpishared.c -qopenmp -o mpishared.out
$ mpirun -n 8 ./mpishared.out
Elapsed time in msec:5699 (after 64 iterations)

为了探索线程并行性,每个内核运行 4 个线程,重新编译 –xMIC-AVX512,以充分利用英特尔® 高级矢量扩展指令集 512(英特尔® AVX-512)指令:

$ mpiicc mpishared.c -qopenmp -xMIC-AVX512 -o mpishared.out
$ export OMP_NUM_THREADS=4
$ mpirun -n 8 ./mpishared.out
Elapsed time in msec:4535 (after 64 iterations)

由于系统中的 MCDRAM 目前被配置为扁平,英特尔至强融核处理器显示两个 NUMA 节点。节点 0 包含所有 CPU 和平台内存 DDR4,节点 1 包含封装内存 MCDRAM:

$ numactl -H
available:2 nodes (0-1)
node 0 cpus:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
node 0 size:98200 MB
node 0 free:92775 MB
node 1 cpus:
node 1 size:16384 MB
node 1 free:15925 MB
node distances:
node   0   1
  0:10  31
  1:31  10

为了分配 MCDRAM(节点 1)中的内存,运行以下命令,将参数 –m 1传递至命令 numactl

$ numactl -m 1 mpirun -n 8 ./mpishared.out
Elapsed time in msec:3070 (after 64 iterations)

这个简单的优化技巧极大地提升了性能速度。

总结

本白皮书介绍了 MPI-3 共享内存特性,提供了使用 MPI-3 共享内存 API 的示例代码。伪代码说明了运行的程序和共享内存 API。该程序运行于英特尔至强融核处理器,我们利用简单的技术进一步优化了该程序。

参考资料

  1. MPI 论坛,MPI 3.0
  2. 消息传递接口论坛,MPI:消息传递接口标准版 3.0
  3. 麻省理工学院出版社,《使用高级 MPI》
  4. James Reinders 和 Jim Jeffers,出版商:Morgan Kaufmann,第 16 章 - MPI-3 共享内存编程介绍,《High Performance Parallelism Pearls》第二册

附录

该示例 MPI 程序代码可通过下载获取。

面向 Caffe* 的定制示例:异或和形状

$
0
0

下载代码示例 [62.34 KB]

简介

Caffe* 是伯克利愿景和学习中心开发的一款深度学习框架,该框架使用 C++ 语言编写,拥有一个 C++ API,并与 Python 和 MATLAB 绑定。

可通过 GitHub 网页https://github.com/BVLC/caffe获取源代码、示例和文档。但是,对于新手开发人员而言,示例和文档带来了很多问题,开发人员需要花费大量的时间和精力进行学习,才能利用该框架自定义操作。

本文通过两个示例展示了如何配置 Caffe,以及如何执行两种定制训练和分类任务:

  • 利用随机生成的异或数据训练网络,并利用经过训练的模型进行分类
  • 利用随机生成的形状(正方形和圆形)训练网络,并利用经过训练的模型进行分类

本文没有详细描述 Caffe 架构或主要用途(图像识别),但是您可以通过访问http://caffe.berkeleyvision.org进一步了解。

随附的源代码假设读者熟悉 Caffe C++ API、Google* 协议缓冲区 (protobufs) 和在 Ubuntu* 16.04 LTS 环境中创建、运行与安装 Caffe 的流程。此外,由于 CMake 设施是创建示例的基础,本文假设读者能够熟练使用 CMake 设施。最后,需要在系统上安装 OpenCV v3.0,便于创建和执行形状。

概述

利用 Caffe 训练网络总共分为 4 步:

第一步 - 准备数据:在本步骤中,准备数据并将其存储为便于 Caffe 使用的格式。我将编写一个用于数据预处理和存储 C++ 应用。

第二步 - 模型定义:在本步骤中,我们创建了一个网络拓扑/架构,并将在扩展名为 .prototxt 的配置文件中定义它的参数。

第三步 - 解析器定义:解析器负责模型优化。在包含扩展名 .prototxt 的配置文件中定义解析器。

第四步 - 模型训练:执行来自终端的 Caffe 命令以训练模型。训练结束后,经过训练的模型位于扩展名为 .caffemodel 的文件中。

训练阶段结束后,我们将利用 .caffemodel 训练模型预测不可见的新数据。为了执行此操作,需要编写一个 C++ 应用。

在示例中,若干步骤被压缩于 shell 脚本内,以帮助读者执行调用的定制程序。

示例源代码树概述

源代码树的顶级(根)是 caffe-cpp-samples。下一级是 /src 目录。/src 目录包含异或和形状的目录名称,它们分别保存了示例的代码和脚本。

CMake 文件的名称为 CMakeLists.txt,包含创建示例和调用 find_package() 函数(以查找 OpenCV 和 Caffe 目录和定义)所需的最小指令集。

在项目的根目录执行以下命令行,完成示例的创建:

cmake .
make all

异或示例

异或示例旨在展示简单的网络拓扑,该拓扑包含隐藏网络,面向异或逻辑函数执行重要的评估。请参考 附录 1,进一步了解创建该示例的历史和数学背景:感知器和异或逻辑

异或示例分为 3 步:

  1. 生成训练数据
  2. 训练网络
  3. 利用网络进行分类

生成训练数据

./generate.sh

本脚本调用创建于 generate-random-xor-training-data.cpp之上的可执行文件,生成 1000 个随机异或示例,并将结果数据置于两个 LMDB 数据库内 - xor_lmdb_trainxor_lmdb_test,每个数据库各分配 500 个示例。

异或函数示例的可能值来自以下真值表:

In1

In2

Out

0

0

0

0

1

1

1

0

1

1

1

0

Out与标签完全相同。

训练网络

./train.sh

默认训练调用已创建的 caffe train,脚本利用来自 solver.prototxt的设置训练 train-test.prototxt定义的网络。最终的准确性为 1,损失应降至最低,接近于 0.0。

利用网络进行分类

./classify.sh

默认分类脚本调用创建于 classify-xor.cpp之上的可执行文件,使用经过训练的模型和来自 deploy.prototxt的网络对 4 种输入组合进行分类(见上表),并显示数值以及是否正确分类。

形状示例

形状示例和异或示例的结构相似,它也可以分解为 3 个步骤:

  1. 生成训练数据
  2. 训练网络
  3. 利用经过训练的模型进行数据分类

生成训练数据

./generate.sh

默认生成脚本调用创建于 generate-random-shape-training-data.cpp之上的可执行文件,生成 1000 多个随机示例,并将这些示例平均分配至两个 LADB 数据库 - shape_lmdb_trainshape_lmdb_test。示例包含所有形状的二乘核和形状的背景。标记每个形状,1 代表正方形,2 代表圆形,0 代表背景。

训练网络

./train.sh

在异或示例中,该默认脚本调用 caffe train,使用来自 solver.prototxt的设置训练 train-test.prototxt定义的网络。最终的准确性应为 1,损失应降至最低,接近 0.0。

利用经过训练的模型进行数据分类

./classify.sh

该分类脚本压缩创建于 classify-shape.cpp之上的可执行文件,使用经过训练的模型和来自 deploy.prototxt的网络对随机生成的图像(包括正方形和圆形)进行分类。最终,显示分类结果图像和错误分类所占的比例。

结论

Caffe 是一款深度学习框架,具有表达式、速度和模块化等特性。然而,这些特性加大了开发人员掌握该框架的难度。本文向读者详细介绍了如何创建并运行两个使用定制网络拓扑的示例

我们鼓励读者通读源代码和 prototxt 文件中的大量评论,深入了解如何面向 Caffe C++ API 编写代码以及如何设置定制网络拓扑。

附录 1:感知器和异或逻辑

多层神经网络为了满足实施异或逻辑门的需求而产生。早期感知器研究人员遇到了异或问题,这也是电子异或电路面临的问题:为了实现异或逻辑,需要多个组件。电子产品通常使用两个非门,两个与门和一个或门。神经网络可能需要多个感知器(在某种程度上说)。更准确地说,需要在指定序列连接各个抽象感知器活动,转换为单个单元的功能。由此产生了多层网络。

为何要耗费精力去创建异或网络?原因有以下两点:(1) 异或门的出现解决了电路设计中的许多问题,(2) 异或网络为设计更有趣的神经网络和机器学习创造了可能。


图 1:异或逻辑电路(Floyd,第 241 页)。

如果您比较熟悉逻辑符号,对比图 1 和图 2,您会发现两个函数的相似之处。两个变频器(非门)和图 2 中 -2 的用处相同。或门函数和图 1 输出单元中的 0.5 激活功能相同。如果您在图 2 的任意处发现了 +1,它们和图 1 中两个与门的操作相同。

感知器受限于布尔代数函数的变体(包括非、与和或),异或函数是一个包含多个单元的混合函数(Floyd,第 241 页)。


图 2:异或门。

需要指出的是,中心单元为了远离外部影响而隐藏,只能通过输入或输出单元连接。隐藏单元的阙值设置为 1.5,确保了两个输入单元均开启的状态下才会启动中心单元。输出单元设置为 0.5,确保了只有净正输入大于 0.5 时才会开启。从隐藏单元到输出单元的 -2 权重确保了开启两个输入后,将启动输出单元。

多层感知器 (MLP) 是一种被称作监督式学习的神经网络,这是因为它必须基于预期输出进行学习。这类网络旨在利用预先选择的数据创建模型,该模型能够将输入正确映射至输出,便于在预期输出未知的情况下利用模型生成输入。


图 3:包含两个隐藏层的 MLP。

输入模式被发送至输入层后,和互联权重相乘,同时从输入层传递至第一个隐藏层。在第一个隐藏层内进行求和,随后利通过非线性激活函数对其进行处理。层处理数据时,首先乘以互联权重,然后求和并等待下一层处理。最终,数据在输出层进行最后一次处理,生成了神经网络输出。

MLP 学习使用反向传播算法。借助反向传播,输入数据被反复展示给神经网络,这个流程被称为训练。每次展示都会对比神经网络的输出和预期输出,并计算错误。随后将错误返回(反向传播)至神经网络,用于调整权重,伴随每次迭代,错误不断减少,神经模型的输出越来越接近预期输出。


图 4:学习模拟异或 (XOR) 数据的神经网络。

异或数据被重复展示给神经网络。通过每次展示计算神经输出和预期输出的错误,并返回至神经网络。神经网络利用错误调整权重,以减少错误。通常在出现了可接受的错误或网络停止学习之前,重复事件序列。

参考文献

Floyd、Thomas L.(2003).《数字基础》(第 8 版)。新泽西:Prentice Hall。

Rumelhart、D. E., Hinton、G. E. 和 Williams R. J. 1986。《Learning internal representations by error propagation》。来自 Rumelhart D. E.、McClelland J. L.等,《Parallel distributed processing:Explorations in the microstructure of cognition》。第 1 卷。剑桥大学:麻省理工学院出版社。

英特尔® 至强® 处理器 E5 v40 有助于提高百度深度神经网络点击率

$
0
0

背景

每天,人们都会为了处理业务、观看视频或购物搜索网站,查找信息。根据 Hubspot 8的报告, “…75% 的用户只会浏览搜索结果的第一页。”如果用户寻找的产品广告碰巧出现在搜索列表的顶部,人们通常会访问这些广告。出现在搜索网页前几页的广告必须在用户中享有较高的知名度,通常需要若干年的积累。如果广告包含了广为人知的信息或产品,或包含热门关键字,也能在搜索列表的前几页显示。

销售产品或服务的新网站如何才能在搜索列表的前几页显示?关键是使用正确的关键字,并与用户搜索产品或服务时使用的关键字相关。

百度1是中国最常用的搜索引擎。为了使广告在搜索列表中的排名靠前,广告公司需要向百度支付一定的费用。如果有人访问/点击了广告,公司需要向百度付费。可以按照点击次数付费 (PPC),也可以根据投放时间的长短支付一定的金额(付款总额和用户点击次数无关)。

为了确定正确的搜索关键字,百度在广告平台及其他应用的核心服务中采用了机器学习2。引擎的核心是点击率 (CTR)3模块。

下文将介绍百度 CTR 及英特尔® 至强® 处理器 E5 v4 产品家族如何提升百度 CTR 模块的性能。

什么是点击率?

根据维基百科的定义,CTR 是点击特定链接的用户数量占浏览页面、电子邮件或广告的用户总数的百分比。

Click-through rate

CTR 能帮助预测广告的相关性,尽可能多地增加用户的点击次数,这么做是因为百度根据点击次数进行收费。

为了实现上述目标,百度采用了深度神经网络 (DNN)。3 DNN 不仅能预测广告的相关性,还可以提升用户访问网站时的体验。通过提升语音和图像识别的准确性提升用户体验。

深度神经网络

维基百科对 DNN 4的定义如下所示:深度神经网络 (DNN) 是一个人工神经网络 (ANN),在它的输入和输出层之间存在多个单元隐藏层。

神经网络 (NN) 通过小规模地模拟大脑皮层的神经结构来效仿人脑的运转。NN 包含 3 层:输入、隐藏和输出层。为了训练 NN,将模式(训练数据集)发送至输入层,基于 NN 的规则,输入层将根据输入模式修改连接的权重。DNN 是一个包含更多隐藏层的 NN。信息从一个隐藏层传输至下一个隐藏层的过程中会结合更复杂的信息。因此,相比 NN,DNN 能更准确地模拟输入模式。

Baidu-webops-2271-fig1

图 1:深度神经网络图。

图 1 显示了包含 4 个隐藏层的典型 DNN。一般而言,隐藏层数越多,训练数据集越大,预测结果会更准确。百度正使用非常庞大的数据集训练 DNN。例如,使用 100 多亿个示例来训练语音识别,用于训练图像识别引擎的图像高达 1000 亿张左右。


百度 CTR 和英特尔® 至强® 处理器 E5 v4 产品家族是一对绝佳组合

百度利用大型数据集训练它的 DNN 模块。有时,训练过程会持续数周的时间,可以通过增强计算能力来减少训练时间。百度的 DNN 大量使用了 DGEMM - 一款面向浮点数的矩阵乘法函数。5 DGEMM 是在百度 DNN 完全连接层计算两个示例的相似性的核心操作,有助于计算 CTR。

百度的 DNN 使用了英特尔® 数学核心函数库(英特尔® MKL)6提供的 DGEMM 函数,以替换 DGEMM 代码。英特尔至强处理器 E5 v4 产品家族支持英特尔® 高级矢量扩展指令集 2(英特尔® AVX2),7 利用英特尔 AVX2 对英特尔 MKL 进行了高度优化,最终提升了百度 DNN 的性能。由于英特尔 MKL 能自动检测和利用新特性(如果适用),因此,无需修改代码便能充分利用下一代英特尔® 至强® 处理器的新特性,这是英特尔 MKL 的另一大优势。请务必将应用连接至最新版英特尔 MKL。

性能测试流程

为了证实英特尔 AVX2 和更强大的硬件能够提升百度 DNN 的性能,我们在两个平台上运行了测试。一个系统配备了英特尔®至强® 处理器 E5-2699 v3,另一个系统配备了英特尔® 至强® 处理器 E5-2699 v4。

测试配置

搭载英特尔至强处理器 E5-2699 v4 的系统

  • 系统:预生产
  • 处理器:英特尔至强处理器 E5-2699 v4 @2.2GHz
  • 高速缓存:55 MB
  • 内存:128 GB DDR4-2133MT/秒

搭载英特尔至强处理器 E5-2699 v3 的系统

  • 系统:预生产
  • 处理器:英特尔至强处理器 E5-2699 v3 @2.3GHz
  • 高速缓存:45 MB
  • 内存:128 GB DDR4-2133 MT/秒

操作系统:CentOS*

软件:

  • GNU* C 编译器套装 4.8
  • 英特尔 MKL 2016 更新 1

应用:百度机器学习深度神经网络 CTR

测试结果

英特尔至强处理器 E5-2699 v4 的计算能力有助于缩短百度训练 DDN CTR 模块的时间,并能提供更好的用户体验。

Figure 2

图 2:采用英特尔® 高级矢量扩展指令集(英特尔® AVX)和英特尔® 高级矢量扩展指令集 2(英特尔® AVX2)的应用对比。

图 2 显示采用英特尔® 高级矢量扩展指令集(英特尔® AVX)和英特尔 AVX2 的应用在英特尔至强处理器 E5-2699 v4 的系统上的测试结果。英特尔 AVX2 支持百度 CTR 搜索引擎的性能提升了 67%。

Figure 3

图 3:使用英特尔® 至强® 处理器 E5-2699 v3 和英特尔® 至强® 处理器 E5-2699 v4 的应用对比。

图 3 显示了搭载英特尔至强处理器 E5-2699 v3 的系统和搭载英特尔至强处理器 E5-2699 v4 的系统的测试结果。由于使用了英特尔 AVX2,以及英特尔至强处理器 E5-2699 v4 拥有更多的内核,性能提升了 23%。

注:在性能检测过程中涉及的软件及其性能只有在英特尔微处理器的架构下方能得到优化。诸如 SYSmark* 和 MobileMark* 等性能测试均采用特定的计算机系统、组件、软件、操作系统及功能进行测量。上述任何要素的变动都有可能导致测试结果的变化。请参考其他信息及性能测试(包括结合其他产品使用时的运行性能)以对目标产品进行全面评估。如欲了解更多信息,请访问:http://www.intel.com/performance

结论

优化 CTR 的核心模块有助于提升百度机器学习模块的速度。由于百度机器学习模块在广告平台及其他百度应用中广泛应用,优化该模块必将提升这些应用的性能。通过使用英特尔 MKL 提供的 DGEMM 函数以及运行搭载英特尔至强处理器 E5 v4 产品家族的系统,CTR 模块的性能得以显著提升。

参考资料

  1. 百度公司信息
  2. 机器学习
  3. 点击率
  4. 深度神经网络
  5. DGEMM
  6. 英特尔® 数序核心函数库
  7. 英特尔® AVX2
  8. http://blog.hubspot.com/insiders/inbound-marketing-stats

数据科学是一个信息的海洋—保持专注!

$
0
0

关于如何成为数据科学家的入门资料

如何成为一名优秀的数据科学家?我应该学习 R* 还是 Python*?还是两者都学?我是否需要获得博士学位?我是否需要上很多数学课?我需要具备哪些软技能才能成功?项目管理经验如何?哪些技能可转移?从何处入手?

Become a data scientist

数据科学是当今科技界的热门话题。科学推动着全球许多趋势的发展,包括机器学习和人工智能。

Become a data scientist在本文中,我们将通过一系列步骤介绍数据科学相关知识,以便对数据科学感兴趣的产品经理或业务经理能够走出迈向数据科学家的第一步或至少加深对其的了解。

第 1 步:定义问题陈述

我们都听到过这样的对话:“查看数据,告诉我你发现了什么。”当数据量比较小、数据大多为结构化数据,且数据信息有限时,这种方法可能有效。但当我们需要处理数 GB 或数 TB 的数据时,这种方法可能会带来无休止、艰巨的检测任务并得不到任何结果,因为没有问题可以着手。

科学虽然强大,但并不是魔法。任何科学领域的发明都可解决一个问题。同样,使用数据科学的第一步是定义一个问题陈述、一个需要验证的假设或一个需要回答的问题。它也可能侧重于要发现的趋势、要作出的预估和预测等。

让我们以用于监控健康和健身的移动应用 MyFitnessPal* 为例。我和我的几个朋友一年前下载了这款应用,然后几乎每天都使用一段时间。但在过去 6 个月中,我们大多数人已经完全不用了。如果我是 MyFitnessPal 的产品经理,那么我可能想要解决的一个问题是:如何提高客户参与度和保留率?

第 2 步:获取数据

如今的数据科学家需要访问多个来源的数据。这些数据可能是结构化数据,也可能是非结构化数据。我们经常获得的原始数据是非结构化数据和/或脏数据,需要对其进行清理和结构化处理,之后才能用于分析。大多数常见的数据源现在提供了在 R 或 Python 中导入原始数据的接口。

常见数据源包括:

  • 数据库
  • CSV 文件
  • 社交媒体源,如 Twitter、Facebook 等(非结构化)
  • JSON
  • Web 擦除数据(非结构化)
  • Web 分析
  • 物联网驱动的传感器数据
  • Hadoop*
  • Spark*
  • 客户访谈数据
  • Excel* 分析
  • 学术文献
  • 政府研究文献和图书馆,如 www.data.gov
  • 财务数据,例如来自 Yahoo Finance* 的财务数据

在数据科学领域,常见词汇包括:

  • 观察或示例。这些可以被视为来自典型数据库的水平数据库记录。
  • 变量、信号、特征。这些相当于数据库中的字段或列。变量可为定性或定量。
⇄ 观察或示例相当于数据库中的行。例如:Joe Allen 的客户记录。
 ⇅ 变量、信号、特征 
 相当于列 
 例如:Joe 的身高。 

第 3 步:清理数据

几个术语用于指代数据清理,例如数据再加工、数据预处理、数据转换和数据整理。这些术语都是指准备用于数据分析的原始数据的过程。

数据科学分析中多达 70–80% 的工作涉及数据清理。
数据科学家对数据中的每个变量进行分析,以评估其是否值得作为模型中的一个特征。如果添加变量可提高模型的预测能力,则会被视为模型的预测指标。这样的一个变量被视为一个 特征,所有这些特性共同为模型创建一个 特征向量。这种分析称为 特征工程

有时,变量可能需要进行清理或转换才能作为模型中的一个特征。为此我们编写脚本,也称为 再加工脚本。>脚本可执行一系列函数,如:

  • 对变量进行重命名(有助于可读性和代码共享)
  • 转换文本 (if "variable = "big" set variable = "HUGE")
  • 删减数据
  • 创建新变量或转置数据(例如根据生日计算年龄)
  • 为现有数据补充额外数据(例如根据邮政编码获取城市和州)
  • 将离散数值变量转换为连续范围(例如薪金到薪金范围;年龄到年龄范围)
  • 日期和时间转换
  • 将分类变量转换为多个二进制变量。例如,区域(可能的值为东、西、北、南)的分类变量可以转换为东、西、北、南这四个二进制变量,其中只有一个适用于观察。这种方法有助于在数据中创建更简单的连接。

有时,数据的数值在数量上有所不同,从而使信息难以可视化。我们可以使用 功能缩放来解决此问题。例如,考虑房屋的平方英尺和房间数量。如果我们使房屋的平方英尺数与卧室数量相似,我们的分析将变得更加轻松。

一系列脚本以迭代的方式应用于数据,直到我们获得足够有效的数据进行分析。为了连续提供用于分析的数据,需要利用新的原始数据重新运行一系列数据再加工脚本。数据管道是指适用于原始数据的一系列处理步骤,用于确保其做好分析准备。

Become a data scientist

第 4 步:数据分析与模型选择

现在我们有了有效数据,可以进行分析了。我们的下一个目标是使用统计建模、可视化、以发现为导向的数据分析等功能熟悉数据。

对于简单问题,我们可以使用平均数、中等值、模式、最小值、最大值、平均值、范围、四分位数等进行 简单的统计分析

监督式学习

我们还可以使用监督式学习,其数据集让我们能够访问一组特定特征变量(独立变量)的响应变量(从属变量)的实际值。例如,我们可以根据已离职员工的任职时间、资历和职位从实际数据中寻找趋势 (resigned=true),然后利用这些趋势预测其他员工是否也会辞职。或者我们可以使用历史数据来关联访客数量(独立变量或预测指标)与生成的收入(因变量或响应变量)之间的趋势。然后这种关联可用于根据访客数量预测网站的未来收入。

监督式学习的关键要求是实际数值的可用性以及一个需要回答的明确问题。例如:这名员工是否会离职?预计获得多少收入?数据科学家将其称为 "为现有数据标记响应变量。"

回归是一款用于监督式学习的常用工具。单因素回归使用一个变量;多因素回归使用多个变量。
线性回归假设因子与响应变量之间的未知关系是线性关系 Y = a + bx,其中 b 是 x 的 系数

现有数据的一部分被用作 训练数据,以计算这一系数的数值。数据科学家通常使用 60%、80% 或 90%(偶尔)的数据进行训练。一旦为 训练模型计算系数的数值,则将利用剩余数据(也称为测试数据)进行测试,以预测响应变量的数值。预测响应值与实际值之间的差异是称为 测试误差指标的有效指标。

我们在数据科学建模方面的探索是为了 最大限度降低测试误差指标,从而通过以下方式提高模型的预测能力:

  • 选择有效的因子变量
  • 编写有效的数据再加工脚本
  • 选择合适的统计算法
  • 选择所需的测试和训练数据量

非监督式学习

当我们尝试学习基础数据本身的结构时,就采用非监督式学习。它没有响应变量。数据集未标记,原有洞察不明确。我们什么都不清楚,所以不打算预测什么!
这种方法对探索性分析有效,可用于回答下列问题

  • 分组。我们有多少类客户群?
  • 异常检测。这种情况正常吗?

方差分析 (ANOVA)是一种常用技术,用于比较两个组或多个组的平均数。它被称为 ANOVA,因为“方差估计”是计算的主要中间统计数据。使用各种距离度量比较不同组的平均数,其中欧氏距离是一种常用方法。

方差分析用于将观察值分为类似的组,也称为 集群。可以根据相应的预测指标将观察值 分类到这些集群中。
http://www.statsdirect.com/help/content/analysis_of_variance/anova.htm

两个常见的聚类应用为:

  • 分层聚类。一种自下而上的方法。我们从单独的观察值开始,并将它们与最接近的观察值进行合并。然后,我们计算这些分组观察值的平均数,并将这些组与最接近的平均数进行合并。我们将重复进行这一工作,直到形成更大的组。距离度量是提前定义的。这种方法很复杂,不适用于高维数据集。

    18/5000 分层方差分析
    Become a data scientist

  • K 均值聚类。使用分区方法。
    • 根据我们的直觉,我们假设数据具有固定数量的集群
    • 我们还假设了 每个集群的起始中心
    • 然后将每个观察值分配给具有最接近观察值的平均值的群集
    • 重复这一步骤,直到所有观察值都已分配给集群。
    • 现在,我们根据分配给集群的所有观察值的平均值重新计算集群的平均值。
    • 将观察值重新分类到这些新集群中,并重复步骤 c、d 和 e,直到它们达到稳定状态。

如果未达到稳定状态,我们可能需要对开始时假设的集群数量(即 K)进行改进,或使用另一个距离度量。

第 5 步:可视化和有效通信

最终的集群可实现可视化,以便使用 Tableau* 或图形库等工具进行简单通信。

数据科学实践者的提示

在我了解数据科学的过程中,我遇到了在 Facebook、eBay、LinkedIn、Uber 和一些咨询企业等公司工作的实践者,这些公司正在有效地利用数据。这是我获得的一些重要建议:

  • 了解您的数据。充分了解数据及其背后的假设非常重要。否则数据可能无效,这可能导致错误的答案、解决错误的问题,或两者兼有。
  • 了解领域和问题。数据科学家必须深入了解业务领域和要解决的问题,以便从数据中提取适当的洞察。
  • 道德规范。不要为假设而牺牲数据质量。问题往往不是无知,而是我们先入为主的观念!
  • 较大的数据集总能够提供更出色的洞察,这是一个谬论。虽然较大的数据量在统计上有显著意义,但大数据集也会带来更大的噪声。经常可以看到,较大数据集的 R 平方值小于较小数据集的 R 平方值。
  • 虽然数据科学本身不是一个产品,但它可以为解决复杂问题的出色产品提供支持。有效沟通的产品经理和数据科学家可成为强大的合作伙伴:
    • 产品经理首先介绍要解决的业务问题、要解答的问题以及要发现和/或定义的限制。
    • 数据科学家在机器学习和数学方面拥有丰富的专业知识,专注于业务问题的理论方面。现代数据集用于执行数据分析、转换、模型选择和验证,以建立应用于 业务问题的理论基础
    • 软件工程师致力于实施理论和解决方案。他或她需要对机器学习(Hadoop 集群、数据存储硬件和编写生产代码等)的机制有很强的理解。
  • 学习编程语言。Python 最容易学习; R 被视为最强大的语言。

常用的数据科学工具

R

R 是一款许多数据科学家喜欢的工具,在学术界拥有特殊的地位。这款工具从数学家和统计学家的角度处理数据科学问题。R 是一种丰富的开源语言,约有 9,000 个额外软件包。用于在 R 中编程的工具称为 R Studio*。尽管 R 在企业中的采用率一直在稳步增长并且其普及在一定程度上归功于其丰富、强大的基于正则表达式的算法,但 R 学习起来比较复杂。

Python

Python 正在逐渐成为数据科学界使用最广泛的语言。像 R 一样,它也是一种开源语言,主要由软件工程师使用,这些工程师将数据科学视为一款使用数据解决面向客户的真正业务问题的工具。Python 学习起来比 R 简单,因为 Python 强调可读性和生产力。Python 也更加灵活和简单。

SQL

SQL 是用于与数据库交互的基本语言,是所有工具所必需的语言。

其他工具

  • Apache Spark 提供 Scala*
  • MATLAB*是一个学术界长期使用的数学环境。它提供一个名为 Octave* 的开源版本
  • Java* 用于 Hadoop 环境

需要哪些软技能?

下文将介绍您需要具备的重要软技能,您可能已经具备其中许多技能。

  • 沟通。数据科学家无法独自坐在办公室里对 Python 程序进行编码。数据科学需要您与团队进行合作。您需要与高管、产品负责人、产品经理、开发人员、大数据工程师和 NoSQL *专家等各种人员进行沟通并建立融洽的关系。您的目标是了解他们正在试图构建什么,以及数据科学和机器学习能够起到怎样的帮助作用。
  • 指导。作为一名数据科学家,您需要拥有出色的指导技能。您并不是公司的独立贡献者;您是首席执行官的最好伙伴,可帮助其塑造公司,即基于数据科学塑造产品和领域。例如,根据您的数据科学结果,您向管理团队提供透视分析结果,建议公司在巴西推出深绿色的鞋子; 如果这款产品投放在美国硅谷,则必将失败。您的发现可以为公司节省数百万美元。
    Become a data scientist
  • 出色的故事叙述者。好的数据科学家是一个很好的故事叙述者。在开展数据科学项目的过程中,您将拥有大量的数据、理论和结果。有时您会感到自己已经迷失在数据的海洋之中。如果发生这种情况,请退一步思考:我们想实现什么目标?例如,如果您的受众是首席执行官和首席运营官,他们可能需要根据您的演示在几分钟内作出决定。他们不关心您的 ROC 曲线,也不会浏览多达 4 TB 的数据和 3,000 行的 Python 代码。

    您的目标是根据可靠的预测算法和准确的结果为他们提供直接建议。我们建议您创建 4 到 5 张幻灯片,在幻灯片中利用可靠的数据和研究清楚地讲述这一故事。可视化。良好的数据科学家需要使用可视化来传达结果和建议。您不能让别人读一份长达 200 页的报告。您需要使用图片、图像、图表和图形来呈现。

  • 思维模式。一个好的数据科学家具有“黑客”思维(这里的“黑客”是褒义)并且不断寻找数据集中的模式。
  • 喜欢数据。您需要使用数据并从中挖掘价值。当然,您可以使用很多工具来更全面地了解数据,但只需大致浏览即可获取很多信息。

我能成为什么?

现在是时候决定了。我应该成为什么类型的数据科学家?

Become a data scientist

  • 了解管道。您需要从某个地方入手。您可以在数据科学项目中担任 Python 开发人员。您可以收集日志、传感器、CSV 文件等来源的输入数据。您可以编写脚本来使用和导入传入数据。数据既可以是静态数据,也可以是动态数据。您可能会决定成为一名使用 Hadoop 或 Hive* 等技术的大数据工程师。或者,您也可能会决定成为一名机器学习算法专家,即掌握相关技能并了解哪种算法最适用于哪类问题的人。您可能是一个数学天才,自由使用开箱即用的机器学习算法并根据自己的需求进行修改。您可能会成为一名数据持久性专家。您可以使用 SQL 或 NoSQL 技术来持久存储/提供数据。或者,您可能成为数据可视化专家,使用 Tableau 等工具构建仪表盘和数据案例。因此再检查一下上面的管道:从导入到可视化。创建机会清单。如 "D3 expert, Python script expert, Spark master"等。
  • Become a data scientistCheck out the job market.看看各种工作门户,了解当前需求。有多少工作可供选择?什么工作的需求最高?薪资结构是什么?大致浏览一下海湾地区有前途的数据科学工作 ►
  • 了解自己。您已经了解了可以获得的管道和工作类型。现在该思考一下自己和自己的技能了。您最喜欢什么,您有什么经验?您是否喜欢项目管理?数据库呢?想想自己以前的成功案例。你喜欢编写复杂的脚本来关联和操作数据吗?您是否从事可视化工作,擅长创建引人注目的演示?创建一个“喜欢从事工作的清单”。 例如“喜欢编码、喜欢脚本、喜欢 Python”。
  • 创建匹配。根据您的喜欢从事工作清单创建机会清单并继续开展计划。数据科学是一个信息的海洋。保持专注!!
Viewing all 583 articles
Browse latest View live