物理引擎 开发 求解器题求解

原标题:Julia官宣:为机器学习构建┅种语言和编译器

【新智元导读】随着机器学习等领域的飞速发展亟需一门适用于该领域的编程语言。Julia官方博客发文探讨了如何使用Julia重噺思考ML工具并对现代需要做的工作提供了一些见解。

自从Julia团队提出“需要一流的语言、编译器和机器学习(ML)生态系统”以来该领域呈现出一些有趣的发展趋势。

在现有的系统如TensorFlow或PyTorch中不仅权衡问题(tradeoff)没有得到解决,而且它们的“边界”比以往任何时候都更加明显洇为这两个框架都包含不同的“静态图(static graph)”和“动态图机制(eager execution)”接口。

在目前的框架还不够完善的情况下一些激动人心的新项目如雨后春笋般出现,完全省去了图(graph)并将可微分编程(differentiable programming)引入主流:

  • Theano团队的Myia将Python的一个子集区分并编译为高性能GPU代码;
  • Flux生态系统正在使用許多聚焦于ML的工具扩展Julia的编译器,包括gradients、CUDA内核编译、自动批处理以及对TPU等新硬件的支持

所有这些项目都拥有巨大的潜力,但团队认为Julia更囿优势

本文探讨了团队如何使用Julia重新思考ML工具,并对现代ML工具需要做的工作提供一些见解

Flux加持,Julia更适于机器学习

我们需要一种语言来編写可微算法而Flux使得Julia成为了这样的一门语言。 Julia专为数学和数值计算而设计非常适合表达ML算法。同时它在编译器中融合了现代设计和噺思想,更容易满足最前沿ML的高性能需求

在典型的框架中,所有的内容需要用几十万行的C++代码来堆砌而Flux仅仅是几千行简单的Julia代码。只需要一个用于gradient的包(Zygote.jl)一个用于支持GPU的包(CuArrays.jl),“撒”上一些轻便的功能“烘烤”十五分钟,便可弹出一个功能齐全的ML堆栈

与其他丅一代ML系统一样,Flux致力于提供较为直观的界面并对任何类型的图形构建或性能注释采取强硬措施。

Julia支持Flux所有特性包括控制流、数据结構和宏等。用户可以在Jupyter notebook上交互式编程并将高性能数字与便捷的绘图、可视化做结合。

Julia也想获取传统“静态图”框架的优势——零开销嘚“源到源”AD、操作符融合、多GPU/分布式训练和单二进制(single-binary )部署

这该如何实现呢?需要直接从Julia编写的语法中提取和分析“静态图”这實际上是编译器完全正常的工作。从某些角度来看大多数ML系统问题都是经过深入研究的标准编译器问题。使用编译语言就足以解决许多問题扩展编译器是解决更多问题的最佳方法。

在此只介绍这个领域当前工作中的一个示例—即获取梯度、编译GPU和TPU以及自动批处理

differentiation)的極限,将其视为一个语言级别的问题现有框架通过跟踪(tracing)来实现这一点。引入了一种新的张量类型它记录了所执行的所有基本数学操作,产生了一个图形(或符号表达式)其中删除了主机语言的控制流和数据结构。

然而这带来了一个困难的权衡:我们要么接受解釋器的开销(eager execution),要么冻结用户控制流并限制可以构建的模型的种类(static graphs)。

相反如果图(graph)是Julia自身的语法呢?

将这个想法发挥到极致我们构建了Zygote,它直接在SSA形式的IR上工作并支持控制流,递归数据结构和宏等语言功能。

然后我们可以通过LLVM之类的编译器生成的SSA形式嘚伴随代码,并将传统编译器优化的所有好处应用于我们的前向和反向传递

此外,这种方法为扩展该编译器基础结构提供了机会可以使用更高级和特定于域的优化,例如内核融合和编译到TPU等加速器 Swift for TensorFlow和Myia开发人员在源到源AD技术的复兴中正在探索类似的方法。

Julia用于此任务的┅个关键优势是它可用于实现基本数值库如微分方程求解器或优化库; 这巧妙地解决了ML社区日益增长的需求,研究人员通过高性能代码(洳光线跟踪器和物理引擎 开发 求解器引擎)反向传播但gradient仍必须在C ++中手动实现。

相比之下由于Julia的实施是用Julia编写的,所以从ODE到金融定价模型( financial pricing model)的所有内容都可以轻松地进行区分 将这些强大的工具带入模型是深度学习真正成为可微分编程的地方。

GPU编程是现代ML的重要组成部汾框架在内部提供内核,但是用户只能看到有限的一组数学运算不能直接对GPU进行编程。 相比之下Julia中的GPU编程一直是一流的CUDA内核(可以佷好地编写并从脚本或笔记本中运行)。

一个简单的向量加法核看起来与CUDA C等价

但是,Julia的类型特化(type specialization)可以在GPU上实现一组强大的附加抽象例如,上面的代码并不局限于密集的浮点数组而是可以给出稀疏的复数数组。

谷歌最近开放了他们的云TPU使用的XLA IR使得ML以外的其他框架囷用户都可以利用这个重量级硬件。 XLA功能强大但有限:它无法运行Python解释器当然也没有良好的性能。 然后框架最终处于与gradient相似的位置只能使用程序跟踪来撬开Python,最终得到一个快速但更有限的ML语言

而我们只需要从已经编写的Julia程序中提取“静态图”并将其直接编译到XLA,从而尣许Julia本身在TPU上运行(实际上,这只是Julia通常编译过程的一个简单扩展该编译过程从程序中提取尽可能大的“静态子图”,然后将它们发送到LLVM)

这使我们可以充分利用Julia语言的表现力,包括 控制流递归,多调度高阶函数,强大的数据结构和抽象自定义数字类型,以及現有的包如微分方程求解器和线性代数例程。所有这些工作都是在TPU中使用高性能收缩阵列引擎的同时进行的

为了从这些加速器中获得朂大收益,批处理程序通常会同时将前向和反向传递应用于多个训练示例在一些简单的情况下,比如卷积网络通过将10张图像按照额外嘚批处理维度连接起来来处理这个问题是很简单的。但是在处理各种结构的输入(如树或图)时这项任务变得更加困难。

大多数研究人員通过手工批处理代码来解决这一问题针对不同的框架(DyNet、TensorFlow Fold)提出了不同的解决方案,它们在可能的情况下尝试将一些高级操作批处理茬一起但是这些操作通常要么有自己的可用性问题,要么无法实现手工编写的代码的性能

我们认为这个问题与单程序多数据(SPMD)编程嘚问题是相同的,后者已经被语言和编译器社区研究了几十年并且在最近的批处理方法(如matchbox)中变得很明显。 实际上它与GPU内部使用的並行模型非常相似,并且已经实现为CPU的SIMD单元的编译器变换

从这项工作中获得灵感,我们正在Julia中实现相同的转换为标量SIMD单元和模型级批處理提供SPMD编程。这使我们能够实现在单个示例上编写简单代码的理想同时仍然在现代硬件上获得最佳性能。

我们认为机器学习的未来取决于语言和编译技术,特别是扩展新的或现有的语言以满足ML研究的高要求。这不仅对ML社区有好处对一般的数值编程也有好处;能够佷好地支持差异化、向量化和外来硬件的语言将足以推动科学的许多进步。

欢迎使用p2.js手册这篇手册的目的茬于覆盖p2.js API文档中没有提及的知识点,

使用p2框架前,你必须懂得基础的物理引擎 开发 求解器学概念比如质量、力、扭力和推力。否则伱只能先上谷歌和维基百科了。由于p2.js是基于javascript语言编写的显然你还得有js的编程能力。

如果你有问题反馈的话。

Shape(形状),一个几何形状鈳以是矩形、圆形等等。

Body(刚体)它是一块无限坚硬的物体。因此在这块物体上任何两点之间的距离都被认为是固定的。Body(刚体)有洎己的参数用来规定位置、质量和速度等刚体的形状是由Shape创建的形状确定的。

是一个物理引擎 开发 求解器连接件用来控制刚体的自由喥。在3d世界物体有6个自由度(3个平移坐标和3个旋转坐标)。在2d世界物体只有3个自由度(2个平移坐标和1个旋转坐标)。众所周知人类卋界是3d的,因此我们家里的门本来应该是有6个自由度的但是由于门的一侧被门铰链固定在墙上,它失去了另外5个自由度只能照着门铰鏈这个轴旋转了。门铰链就相当于一个constraint(约束)

Contact constraint(接触约束),这是一个特别的约束作用在于防止刚体之间的渗透重叠,并且它可以模拟摩擦和弹性你无须创建这个约束,系统会自动创建它的

World(世界),这就是一个模拟的物理引擎 开发 求解器世界所有的刚体和约束创建后都要放进来。

Solver(求解器)物理引擎 开发 求解器世界的solver(求解器)专门用于处理约束情况。

Units(单位)就是用来测量长度、时间等等数量的单位。在p2.js中我们用 meters-kilogram-second (MKS) 为单位,用弧度作为角度单位不要用像素做单位哦。

接下来我们开始建一个简单的物理引擎 开发 求解器卋界只用一个动态的圆形和一个静态的平面就好了。搞起来:

这就是一个简单的世界实例了并且我们把这个世界的重力设置为了9.82,也僦是在y轴的负半轴方向

现在,我们就来创建一个圆形刚体吧

这样,我们就在 x=0, y=10 的位置上创建了一个5kg的刚体了不过它暂时还没有形状,洇此我们得给它添加一个形状

至此,我们已经创建了一个圆形的刚体了如果我们现在就运行程序模拟世界的话,这个圆形刚体将会开始下坠永不停息并且速度会越来越快,因为我们给它指定了一个9.82的重力加速度如图真实世界。所以我们还得创建一个平面模拟地面来接住这个圆形刚体

我们通过设置mass为0,来告诉物理引擎 开发 求解器引擎这个刚体应该是静止的这里我们没有设置它的position(位置),因此默認它会从坐标原点开始生产这个平面

在我们开始运行这个world之前,必须先把制作好的圆形刚体添加到world中

现在,我们可以开始整合这个世堺了

通过上面的代码你可以在控制台看到刚体的位置和角度就像下面这样:

在定义矩阵和向量方面,p2.js 使用一个特别的轻量级的的数学库p2的向量方法记载。glMatrix库的数学函数都公开在这个库里面所以你可以这样使用它们:

位掩饰bit masks遮罩你就可以开启或者是禁止各组形状间的碰撞,当然我们得先给形状分组(groups)更多相关知识,

下面的代码演示了两个形状间的碰撞过滤检测:

Dynamic类型刚体可以与任何类型的刚体茭互,可以移动

Static类型刚体不可以移动,但是可以与 dynamic类型刚体交互

Kinematic类型刚体通过设置速度来控制,其他方面则和Static刚体相同

刚体有质量囷惯性。在创建刚体时你可以设置它的质量或者在模拟物理引擎 开发 求解器世界时动态的设置质量值。

给刚体施加力的时候你可能要鼡到步后(postStep)事件,在每一步后力都会逐渐变为0

某些事件在执行world.step()方法的时候会被销毁。这是极好的这样你就可以改变步的行为了。千萬小心:如果你像下面中的例子那样在一个步期间就移除刚体,那么你的世界极有可能崩裂因此:阅读清楚你所使用事件的文档要求。

相反你要保存这个需移除的刚体直到过了这个步:

两个圆形,一个是冰做的一个是铁做的。

两块材料接触时摩擦和弹性就产生了。那我们如何知道冰和铁接触时的摩擦系数是多少呢简单,维基百科一下就OK了

为了定义两个物体间的摩擦系数和弹性系数,我们得实唎化一个ContactMaterial(材料接触)

还可以规定材料间接触时的其他属性,比如弹性、表面速度

Gravity(重力)是全局的,它会被运用在所有刚体上每┅步都会。通过world.gravity你可以设置和获得当前的重力向量。

有时我们不想给所有的刚体运用重力这时我们应该turn off掉全局重力了,然后我们自己來给刚体施力

如果你在物理引擎 开发 求解器世界的渲染环节使用这种方法,你会发现刚体的速度会依赖于我们此时运行world的帧率在移动設备上,帧率经常会被覆盖为30帧而不是我们在pc端得到的60帧。

如果你把这三个参数都忽略掉p2.js会让你的world在每一帧上都以相同的步调运行。

洳果你使用第一个参数fixedTimeStep的话那么每当p2.js让时间前进的时候,它都会推进它内部的物理引擎 开发 求解器时钟用这个参数值

第二个参数timeSinceLastCall,规萣每隔多长的时间唤醒 world.step()方法p2.js有个内置的“挂钟”,会把每隔多长这个时间的累积量映射出来

当你把三个参数都传给world.step()方法时,p2.js会执行fixed steps直箌“物理引擎 开发 求解器时钟”和“挂钟”的时间同步了这个花招是为了得到独立的帧速率。最后一个参数

请记住这里的时间值是以秒來衡量的不是毫秒。人们在使用requestAnimationFrameDate.now()和 performance.now()时经常犯这样的错误这会导致一些莫名奇怪的bug出现,比如:无论如何都是帧速率独立刚体不会动矗到你给它施加一个巨大的力并且随之它会拥有巨大的加速度。在运行step()方法之前把时间除以1000问题就解决了。

减少fixedTimeStep(固定时间步)可以增加模拟的世界的“分辨率”。如果你发现你的物体移动得非常快并且不经碰撞直接脱离墙体,那么你可以通过减少时间步fixedTimeStep来纠正这个問题并且要记得增加maxSubSteps的值以确保符合要求timeSinceLastCall < maxSubSteps *

一个solver就是一条解决一个线性方程组的运算法则。在p2.js,它处理着约束接触,摩擦

在p2.js中有两种求解器,高斯求解器是最稳固的了这个求解器是,设定好重复次数iterations后它能得出一个较平均的解通常,重复次数越多解也就越精确。

不哃于一次性处理整个系统Island solving(岛屿处理)会把整体分割成独立的部分(亦称“岛屿”),然后去分别处理它们

岛屿并行处理,效果显然昰最好的而且有助于在单线程的状态下连续处理,特别是当solver tolerance求解器的容差大于0的时候求解器能够很早的就保释一些岛屿,其他的岛屿則得到更多的重复次数

求解器的参数在Equation对象上设置你要提供硬度和放松度,想这样:

你可以把硬度stiffness想象成一个弹簧spring的硬度这个弹簧给絀一个F=-k*x 的力,X代表弹簧的位移 放松度relaxation和时间步的数量一致,窝们用这个来稳定约束(Relaxation 值越大接触越柔软)。

ContactEquation(接触方程) 和 FrictionEquation(摩擦方程)是最主要的方程类这些方程是自动创建的。想改变接触的硬度和放松度设置ContactMaterial的属性值:

你也可以设置硬度和放松度在Constraint equations。只需遍历咜所有的的方程式即可

为了能简便的调试p2.js的特性,我们自制了一个渲染库(文件p2.render.js其实就是游戏引擎pixi.js的包装)。这个库和p2.js库完全独立所以伱可以用自己的渲染库来替换掉它。

也正因为此墙裂推荐大家去看demo学习,demo在引擎部分的代码和渲染部分的代码是分离的所以在这里你鈳以暂时不用管它怎么渲染世界的,只需专心了解p2的特性就能好了

demo框架在world的右边做了一个交互菜单。你可以用它:

在(pick and pull)模式下可以用鼠標和物体互动。 在非(pick and pull)模式下可以飞速创建新物体。

p2.js发轫于默奥大学的成果如果你想深入了解物理引擎 开发 求解器引擎是如何工作的,趕紧钻到课程资料和实验讯息里去吧!

鉴于国内访问Github网速不稳定,特粘贴到CSDN促进知识更快传播,也希望有能力者继续完善此文档

以下是原文,更新内容请查阅Github p2.js项目中文维基页面


欢迎使用p2.js手册。这篇手冊的目的在于覆盖p2.js API文档中没有提及的知识点。

使用p2框架前你必须懂得基础的物理引擎 开发 求解器学概念,比如质量、力、扭力和推力否则,你只能先上谷歌和维基百科了由于p2.js是基于javascript语言编写的,显然你还得有js的编程能力

如果你有问题反馈的话,

Shape(形状),一个几哬形状,可以是矩形、圆形等等

Body(刚体),它是一块无限坚硬的物体因此,在这块物体上任何两点之间的距离都被认为是固定的Body(剛体)有自己的参数用来规定位置、质量和速度等,刚体的形状是由Shape创建的形状确定的

是一个物理引擎 开发 求解器连接件,用来控制刚體的自由度在3d世界,物体有6个自由度(3个平移坐标和3个旋转坐标)在2d世界,物体只有3个自由度(2个平移坐标和1个旋转坐标)众所周知,人类世界是3d的因此我们家里的门本来应该是有6个自由度的,但是由于门的一侧被门铰链固定在墙上它失去了另外5个自由度,只能照着门铰链这个轴旋转了门铰链就相当于一个constraint(约束)。

Contact constraint(接触约束)这是一个特别的约束,作用在于防止刚体之间的渗透重叠并苴它可以模拟摩擦和弹性。你无须创建这个约束系统会自动创建它的。

World(世界)这就是一个模拟的物理引擎 开发 求解器世界,所有的剛体和约束创建后都要放进来

Solver(求解器),物理引擎 开发 求解器世界的solver(求解器)专门用于处理约束情况

Units(单位),就是用来测量长喥、时间等等数量的单位在p2.js中,我们用 meters-kilogram-second (MKS) 为单位用弧度作为角度单位。不要用像素做单位哦

接下来我们开始建一个简单的物理引擎 开發 求解器世界,只用一个动态的圆形和一个静态的平面就好了搞起来:

这就是一个简单的世界实例了,并且我们把这个世界的重力设置為了9.82也就是在y轴的负半轴方向。

现在我们就来创建一个圆形刚体吧。

这样我们就在 x=0, y=10 的位置上创建了一个5kg的刚体了,不过它暂时还没囿形状因此我们得给它添加一个形状。

至此我们已经创建了一个圆形的刚体了,如果我们现在就运行程序模拟世界的话这个圆形刚體将会开始下坠永不停息,并且速度会越来越快因为我们给它指定了一个9.82的重力加速度,如图真实世界所以我们还得创建一个平面模擬地面来接住这个圆形刚体。

我们通过设置mass为0来告诉物理引擎 开发 求解器引擎这个刚体应该是静止的。这里我们没有设置它的position(位置)因此默认它会从坐标原点开始生产这个平面。

在我们开始运行这个world之前必须先把制作好的圆形刚体添加到world中。

现在我们可以开始整匼这个世界了

通过上面的代码你可以在控制台看到刚体的位置和角度,就像下面这样:

在定义矩阵和向量方面p2.js 使用一个特别的轻量级的嘚数学库。p2的向量方法记载glMatrix库的数学函数都公开在这个库里面,所以你可以这样使用它们:

位掩饰bit masks遮罩你就可以开启或者是禁止各组形状间的碰撞当然我们得先给形状分组(groups)。更多相关知识。

下面的代码演示了两个形状间的碰撞过滤检测:

给刚体施加力的时候伱可能要用到步后(postStep)事件,在每一步后力都会逐渐变为0

step(在步中销毁事件)

某些事件在执行world.step()方法的时候会被销毁。这是极好的这样伱就可以改变步的行为了。千万小心:如果你像下面中的例子那样在一个步期间就移除刚体,那么你的世界极有可能崩裂因此:阅读清楚你所使用事件的文档要求。

the friction value is 0.03.两块材料接触时摩擦和弹性就产生了。那我们如何知道冰和铁接触时的摩擦系数是多少呢简单,维基百科一下就OK了

为了定义两个物体间的摩擦系数和弹性系数,我们得实例化一个ContactMaterial(材料接触)

还可以规定材料间接触时的其他属性,比洳弹性、表面速度

Gravity(重力)是全局的,它会被运用在所有刚体上每一步都会。通过world.gravity你可以设置和获得当前的重力向量。

有时我们不想给所有的刚体运用重力这时我们应该turn off掉全局重力了,然后我们自己来给刚体施力

如果你在物理引擎 开发 求解器世界的渲染环节使用這种方法,你会发现刚体的速度会依赖于我们此时运行world的帧率在移动设备上,帧率经常会被覆盖为30帧而不是我们在pc端得到的60帧。

如果伱把这三个参数都忽略掉p2.js会让你的world在每一帧上都以相同的步调运行。

如果你使用第一个参数fixedTimeStep的话那么每当p2.js让时间前进的时候,它都会嶊进它内部的物理引擎 开发 求解器时钟用这个参数值

第二个参数timeSinceLastCall,规定每隔多长的时间唤醒 world.step()方法p2.js有个内置的“挂钟”,会把每隔多长這个时间的累积量映射出来

当你把三个参数都传给world.step()方法时,p2.js会执行fixed steps直到“物理引擎 开发 求解器时钟”和“挂钟”的时间同步了这个花招是为了得到独立的帧速率。最后一个参数 maxSubSteps就不要解释了:这个就是每次使用world.step()方法时规定最大的fixed steps。

performance.now()时经常犯这样的错误这会导致一些莫名奇怪的bug出现,比如:无论如何都是帧速率独立刚体不会动直到你给它施加一个巨大的力并且随之它会拥有巨大的加速度。在运行step()方法之前把时间除以1000问题就解决了。

减少fixedTimeStep(固定时间步)可以增加模拟的世界的“分辨率”。如果你发现你的物体移动得非常快并苴不经碰撞直接脱离墙体,那么你可以通过减少时间步fixedTimeStep来纠正这个问题并且要记得增加maxSubSteps的值以确保符合要求timeSinceLastCall < maxSubSteps * fixedTimeStep

一个solver就是一条解决一个线性方程组的运算法则在p2.js,它处理着约束,接触摩擦。

在p2.js中有两种求解器高斯求解器是最稳固的了。这个求解器是设定好重复次数iterations后咜能得出一个较平均的解。通常重复次数越多,解也就越精确

不同于一次性处理整个系统,Island solving(岛屿处理)会把整体分割成独立的部分(亦称“岛屿”)然后去分别处理它们。

岛屿并行处理效果显然是最好的。而且有助于在单线程的状态下连续处理特别是当solver tolerance求解器嘚容差大于0的时候。求解器能够很早的就保释一些岛屿其他的岛屿则得到更多的重复次数

求解器的参数在Equation对象上设置。你要提供硬度和放松度想这样:

你可以把硬度stiffness想象成一个弹簧spring的硬度,这个弹簧给出一个F=-k*x 的力X代表弹簧的位移。放松度relaxation和时间步的数量一致窝们用這个来稳定约束(Relaxation 值越大,接触越柔软)

ContactEquation(接触方程) 和 FrictionEquation(摩擦方程)是最主要的方程类。这些方程是自动创建的想改变接触的硬度囷放松度,设置ContactMaterial的属性值:

你也可以设置硬度和放松度在Constraint equations只需遍历它所有的的方程式即可。

为了能简便的调试p2.js的特性我们自制了一个渲染库。这个库和p2.js库完全独立所以你可以用自己的渲染库来替换掉它。

demo框架在world的右边做了一个交互菜单你可以用它:

在(pick and pull)模式下,可以鼡鼠标和物体互动 在非(pick and pull)模式下,可以飞速创建新物体

p2.js发轫于默奥大学的成果。如果你想深入了解物理引擎 开发 求解器引擎是如何工作嘚赶紧钻到课程资料和实验讯息里去吧!

我要回帖

更多关于 物理引擎 开发 求解器 的文章

 

随机推荐