领域特定语言

下面的内容主要基于Kunle Olukotun在Stanford开设的课程CS 442: High Productivity and Performance with Domain Specific Languages in Scala, 2011, Online。 但这门课是研究性质的,即主要以Stanford Pervasive Parallelism Lab (PPL)组开发的Delite作为基石讲解。 因而在这里我只会将部分通用的重要的章节抽取出来。

简介

DSL Triangle 常见的DSL如

  • 图像处理OpenGL
  • 科学计算Matlab
  • 排版软件TeX
  • 数据库MySQL

DSL的好处

  • 提高生产力
    • 将程序员从复杂的并行编程中隔离开来
    • 注重于算法应用实现而不是底层细节
  • 提高性能
    • 更加符合一般化的并行执行领域高层抽象
    • 限制表达力(expressiveness)进而更易提取可用并行
    • 用领域知识做静态/动态优化
  • 可移植性(portability)与前向可扩展性(forward scalability)
    • DSL和Runtime能够进化到利用最新硬件特性的优势
    • 应用无需改变
    • 允许革新硬件而不用担心应用的可移植性

两种DSL

  • 一种依赖于宿主语言(embeded DSL, “Just a library”)
    • 方便开发,可以重用整个宿主语言
    • 方便学习,只需有宿主语言的基础
    • 能够结合多种DSL在一个程序中
    • 能够共用DSL基础设施
    • 但难以通过领域知识优化
    • 与宿主语言一样面向同一硬件
    • 例子
      • Halide依赖于C++编译到汇编/cuda
      • Chisel依赖于Scala编译到Verilog
  • 一种做更高层的抽象(stand-alone)
    • 能够做大量优化
    • 但需要大量人力来实现一门充分成熟的语言
      • 全套的编译器/优化
      • 工具链(IDE、调试器)
    • 多种DSL之间的交互比较麻烦(这倒不是太大问题)
    • 例子
      • GraphIt直接编译为C++
      • Spatial直接编译为Chisel

需要做得更好,目标是设计一门嵌入式的DSL,但是性能和单一的DSL一样

典型的编译器

  • DSL采用高度可表达的嵌入式语言的前端(Scala)
  • 但可以定制化IR和后端Pass(Delite)
graph LR c --> d subgraph frontend a["Lexer"] --> b["Parser"] b --> c["Type checker"] end subgraph backend d["Analysis"] --> e["Optimization"] e --> f["Code gen"] end

设计DSL

最关键还是3P

  • Portability
    • 自动重定向不同硬件MPI/cuda/…
    • 添加新的硬件需要修改语言吗
  • Performance
    • 常量零开销
    • 增加计算资源可扩展
  • Productivity(通常最难达到)
    • 用户能够通过写你的语言达到更快的并行吗
    • 代码行数

最重要从例子开始,进行泛化(generalize)

  • 尽可能多地寻找这个领域的例子(广度)
  • 从中提取出常见模式
  • 并行化执行
  • 为什么是例子?
    • 让这个领域对非领域专家来说更加具体
    • 确定这种语言应该支持什么特性
    • 并行实施展现如何生成高效的代码
    • 例子间的重叠看看什么是需要被语言所handle的
  • 有效的应用应该是(DSL应该能够自动执行下面这些)
    • 找到并行性
    • 暴露局部性
    • 推出同步性(synchronization)

好的DSL

  • 语言的特性能够将并行性、局部性、同步性暴露出来(platform-independent)
  • 编译器能够自动提取这些知识并重定向到不同架构(platform-specific)

语言(language)与框架(framework)的区别

  • 编程语言主要是一系列的语法语义规则
  • 框架 则是用现成的编程语言写成的一些库(library)/工具(tool)的集合,提供API接口,重用性高(reusable),避免重复造轮子,可以直接调用