Julia:高性能 GPU 计算的编程语言

2017-10-31 18:02    it168网站 原创  作者: 编译|田晓旭 编辑: 田晓旭

  【IT168 评论】Julia是一种用于数学计算的高级编程语言,它不仅与Python一样易于使用,而且还与C一样快。Julia是出于性能考虑而创建的,它的语法与其他编程语言相似,但是却拥有和编译型语言相媲美的性能。

  如今,在多核CPU和大型并行计算系统的编程中,Julia已经非常受欢迎了。随着Julia的发展,其在GPU计算中也受到了众多青睐。GPU的性能可以通过提供更多的高级工具进行民主化,这些工具更易于被应用数学家和机器学习程序员使用。在这篇文章中,我将重点介绍使用Julia软件包CUDAnative.jl进行本地GPU编程,通过本地PTX代码生成功能增强Julia编译器。

  

  图1.使用不同抽象级别的库和Julia包进行GPU编程

  现有的GPU-Accelerated Julia Packages

  Julia包生态系统已经包含了相当多的与GPU相关且针对不同抽象级别的软件包,如图1所示。在最高抽象级别包括类似 和 TensorFlow.jl的域特定包,可以透明地使用系统中的GPU。使用ArrayFire 可以进行更通用的开发 ,如果需要线性代数或深层神经网络算法等专门的CUDA实现,可以使用供应商特定的软件包,如 或 cuDNN.jl。所有这些软件包本质上都是原生库的包装器,利用Julia的外部函数接口(FFI)以最小的开销调用库的API。如果想要了解更多信息,可以点击下面的GitHub地址:https://github.com/JuliaGPU/

  这个列表中缺少的是最低的抽象级别,你可以在CUDA C ++中编写内核并管理执行。灵活的实现或优化现有软件包不能实现的抽象表达算法,是CUDAnative.jl的魅力所在。

  基于CUDAnative.jl的Native GPU Programming

  CUDAnative.jl包添加了原生GPU编程能力的Julia编程语言。与CUDAdrv.jl 或CUDArt.jl 包一起使用时,要分别与CUDA驱动程序和运行时库进行连接,之后就可以在Julia中进行低级别CUDA开发,而无需外部语言或编译器。下面的程序是演示如何计算两个向量的和:

  

  这个例子的真正主力是@cuda macro,它生成专门的代码,用于将内核函数编译成GPU汇编,将其上传到驱动程序,并准备执行环境。与Julia的即时(JIT)编译器一起,形成非常有效的内核启动序列,从而避免了与动态语言相关联的运行时开销。生成的代码也有特定的参数类型; 使用不同类型的参数可以调用相同的内核。

  

  图2. CUDAnative.jl编译器的原理图。

  Julia GPU编译器的设计避免提供自定义工具链来编译(GPU兼容的)Julia源代码到GPU汇编的子代。如图2所示,它尽可能地与现有的Julia编译器集成。只有在生成机器代码的最后一步才会完全支持GPU包。

  重用Julia编译器有很多优点,首先硬件支持微小包:CUDAnative.jl只有1300行代码。其次,CUDAnative.jl避免了多个独立的语言实现,虽然可能会导致语法略有些不同,但同时你也可以像使用GPU代码一样使用Julia实现GPU功能。第三,你可以使用动态类型多方法,元编程,任意类型和对象等。当然这其中也会有一些不兼容或者限制,例如,限制缺乏Julia GPU运行时库、垃圾回收器,不过值得欣慰的是,Julia团队正在不断努力来覆盖更多语言和库。

  示例: Parallel Reduction

  Parallel Reduction是一个很有趣的例子,它是一种用于从输入值序列中计算总和或其他单个值的协作并行算法。本文中列举了Julia代码在一部分。

  以下代码片段显示了使用GPU随机播放指令缩减内部函数。

  

  该函数有两个参数,缩减运算符函数和减小值。Julia编译器基于这些参数的类型生成专用代码,不仅避免了运行时类型检查,而且完全内联函数参数。这可以在下面的代码清单中看到,当与+操作符一起调用此函数时生成PTX代码,以及作为参数的32位整数。

  

  功能专业化是自动的,其赋予了Julia标准库中的大部分通用代码。在这个例子中,它生成了类似于nvcc的非常干净紧凑的PTX代码。

  性能

  前文我们介绍道CUDAnative.jl可以为小功能生成高效的PTX代码,但是其如何支持现实生活中的应用程序?为了评估这一点,Julia团队移植了 来异构加速Julia。因为移植这样的应用程序需要很大的努力,所以我们专注10个小基准。

  图3中的图表比较了这些基准测试的原始CUDA C ++实现与Julia端口的性能。Julia版本几乎是逐字的端口,也就是说,没有算法变化,也没有引入高级概念。如图所示,使用Julia进行GPU计算并不会遭受任何广泛的性能损失。唯一的异常值是nn基准,与CUDAnative.jl相比,由于稍微更好的寄存器使用情况,其性能显着提高。平均来说,CUDAnative.jl端口与静态编译的CUDA C ++相同。

  

  图3.来自Rodinia benchmark suite 几个基准测试的CUDA C ++和CUD

  NVIDIA工具

  CUDAnative.jl还旨在与CUDA工具包中的现有工具兼容。例如,它会生成必要的行号信息,以便NVIDIA Visual Profiler按预期的方式工作,并将 以进行更细粒度的控制。行号信息还可以与cuda-memcheck这样的工具相结合,实现精确的回溯:

  LLVM NVPTX后端不支持完整调试信息 ,因此cuda-gdb无法正常工作。

  高级编程

  Julia动态语言语义的组合、专门的JIT编译器和一级元编程有可能创建非常强大的高级抽象,这在其他动态语言中是很难实现的。例如, CuArrays.jl 包将CUBLAS.jl的性能和CUDAnative.jl的灵活性相结合,提供了与Julia中其他阵列一样的CUDA加速数组。它建立在Julia对高阶函数的支持之上,这些功能是自动且专用的:在CuArray上调用映射或广播会生成专门针对操作和数组类型的内核,与上述reduce_warp示例非常相似。

  此外,Julia最近已经获得了syntactic loop fusion的支持,根据介绍文档显示,假设我们实现了,现在要计算并将结果存储在X中。你可以执行以下操作:

  

  整个计算将融合到单一的GPU内核,性能可以与hand-written 相当。代码是动态类型的,对于CPU阵列甚至是分布式容器,只要实现相关方法,它也同样适用。这被称为 duck typin,它更容易实现真正的通用代码。目前Julia团队正在努力实现所有必需的接口,以使用GPU阵列与ForwardDiff.jl或Knet.jl等软件包。

  除此之外,Julia具有强大的外部功能界面,用于调用其他语言环境。它允许Cxx.jl这样的 ,和用于C ++的FFI,解析相应地头文件并调用函数。同时团队还在使用该接口来创建 CUDAnativelib.jl 来调用CUDA设备库,其中一些库作为模板化的C ++头文件发布。

  前文中在GitHub中列出的许多软件包基本都已经成熟了,支持各种平台和Julia版本。但CUDAnative.jl及其依赖关系还没有那么成熟,例如兼容性方面仅支持Linux和MacOS。感兴趣的朋友可以去尝试!

Julia:高性能 GPU 计算的编程语言的更多相关文章

  1. Julia语言:让高性能科学计算人人可用

    Julia语言:让高性能科学计算人人可用要:一群科学家对现有计算工具感到不满:他们想要一套开源系统,有C的快速,Ruby的动态,Python的通用,R般在统计分析上得心应手,Perl的处理字符串处理, ...

  2. AI芯片:高性能卷积计算中的数据复用

    随着深度学习的飞速发展,对处理器的性能要求也变得越来越高,随之涌现出了很多针对神经网络加速设计的AI芯片.卷积计算是神经网络中最重要的一类计算,本文分析了高性能卷积计算中的数据复用,这是AI芯片设计中 ...

  3. CUDA刷新:GPU计算生态系统

    CUDA刷新:GPU计算生态系统 CUDA Refresher: The GPU Computing Ecosystem 这是CUDA Refresher系列的第三篇文章,其目标是刷新CUDA中的关键 ...

  4. python3使用pycuda执行简单GPU计算任务

    技术背景 GPU的加速技术在深度学习.量子计算领域都已经被广泛的应用.其适用的计算模型是小内存的密集型计算场景,如果计算的模型内存较大,则需要使用到共享内存,这会直接导致巨大的数据交互的运算量,通信开 ...

  5. GPU计算的十大质疑—GPU计算再思考

    http://blog.csdn.NET/babyfacer/article/details/6902985 原文链接:http://www.hpcwire.com/hpcwire/2011-06-0 ...

  6. OpenGL实现通用GPU计算概述

    可能比較早一点做GPU计算的开发者会对OpenGL做通用GPU计算,随着GPU计算技术的兴起,越来越多的技术出现,比方OpenCL.CUDA.OpenAcc等,这些都是专门用来做并行计算的标准或者说接 ...

  7. (Matlab)GPU计算简介,及其与CPU计算性能的比较

    1.GPU与CPU结构上的对比 2.GPU能加速我的应用程序吗? 3.GPU与CPU在计算效率上的对比 4.利用Matlab进行GPU计算的一般流程 5.GPU计算的硬件.软件配置 5.1 硬件及驱动 ...

  8. 多GPU计算

    多GPU计算已经可以说,只要是个成熟的模型,都使用了这一点. 例如: gluoncv:https://github.com/dmlc/gluon-cv/blob/master/scripts/dete ...

  9. OpenCL入门:(二:用GPU计算两个数组和)

    本文编写一个计算两个数组和的程序,用CPU和GPU分别运算,计算运算时间,并且校验最后的运算结果.文中代码偏多,原理建议阅读下面文章,文中介绍了OpenCL相关名词概念. http://opencl. ...

随机推荐

  1. A Tutorial on Network Embeddings

    A Tutorial on Network Embeddings paper:https://arxiv.org/abs/1808.02590   NE 的中心思想就是找到一种映射函数,该函数将网络中 ...

  2. StringBuilder类的作用,以及与String类的相互转换

    # 转载请留言联系 先看一段String类的字符串拼接的代码. String s = "hello" 会在常量池开辟一个内存空间来存储”hello". s += &quo ...

  3. LeetCode解题报告—— Jump Game & Merge Intervals & Permutation Sequence

    1. Jump Game Given an array of non-negative integers, you are initially positioned at the first inde ...

  4. Restful Framework (四)

    目录 一.分页 二.视图 三.路由 四.渲染器 一.分页 回到顶部 试问如果当数据量特别大的时候,你是怎么解决分页的? 方式a.记录当前访问页数的数据id 方式b.最多显示120页等 方式c.只显示上 ...

  5. 数据库之各种键(Key)

    超键(super key):在关系中能唯一标识元组的属性集称为关系模式的超键候选键(candidate key):不含有多余属性的超键称为候选键主键(primary key):用户选作元组标识的一个候 ...

  6. 【hdoj_2391】FilthyRich

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2391 题目大意:给定一个矩阵,从左上角第一个元素开始到右下最后一个元素,寻找一条路线,使得路线经过的矩阵元 ...

  7. spring-web涉及jar包说明

    <!-- spring-context, spring-aop, spring-beans, spring-core, spring-expression --> <dependen ...

  8. 如何把Android Studio项目转换成Eclipse的项目

    1. 找到这个目录:项目名称\app\src\main,并把它导入到Eclipse里 2. 把项目名称\app\libs文件夹拷贝到新生成的项目下,并删除掉.DS_Store文件 3. 这时再看还有什 ...

  9. WebMail

    try { WebMail.SmtpServer = "smtp.example.com";      WebMail.SmtpPort = ;      WebMail.Enab ...

  10. .NET 简单的递归使用场景

    什么是递归:自己调用自己,直到满足条件跳出 递归的缺点: 递归很耗内存,容易让机器挂掉 比如递归文件夹,当文件夹的层级有非常非常多的时候,就很容易挂掉,因为递归的时候把上层文件夹的上下文都保存在内存中 ...