如果我正确地记住了我的编译器课程,那么典型的编译器将具有以下简化的轮廓:
- 词法分析器逐字符扫描(或调用某些扫描功能)源代码
- 根据词素词典检查输入字符的字符串是否有效
- 如果lexeme有效,则将其分类为与其对应的令牌
- 解析器验证令牌组合的语法;逐个令牌。
从理论上讲,将源代码分成四分之一(或其他分母)并在扫描和解析过程中使用多线程是否可行?是否存在利用多线程的编译器?
如果我正确地记住了我的编译器课程,那么典型的编译器将具有以下简化的轮廓:
从理论上讲,将源代码分成四分之一(或其他分母)并在扫描和解析过程中使用多线程是否可行?是否存在利用多线程的编译器?
Answers:
大型软件项目通常由许多编译单元组成,这些编译单元可以相对独立地进行编译,因此,通过并行多次调用编译器,通常可以以非常粗糙的粒度并行化编译。这发生在OS进程级别,并且由构建系统而不是适当的编译器进行协调。我意识到这不是您要的,但这是大多数编译器中最接近并行化的东西。
这是为什么?好吧,编译器所做的许多工作都不容易实现并行化:
在此之后,它变得稍微容易一些。类型检查和优化以及代码生成原则上可以在函数粒度上并行化。我仍然知道很少有编译器这样做,也许是因为同时执行如此大的任务非常具有挑战性。您还必须考虑到,大多数大型软件项目包含如此多的编译单元,以至于“并行运行一堆编译器”方法完全足以保持您所有的内核(在某些情况下甚至是整个服务器场)。另外,在大型编译任务中,磁盘I / O可能与实际编译一样成为瓶颈。
综上所述,我确实知道一个可以并行化代码生成和优化工作的编译器。Rust编译器可以将后端工作(LLVM,实际上包括传统上被认为是“中端”的代码优化)分配给多个线程。这称为“代码生成单元”。与上面讨论的其他并行化可能性相比,这是经济的,因为:
编译是一个“令人尴尬的并行”问题。
没人在乎编译一个文件的时间。人们关心编译1000个文件的时间。对于1000个文件,处理器的每个内核可以一次愉快地编译一个文件,从而使所有内核完全处于繁忙状态。
提示:如果为make赋予了正确的命令行选项,则它会使用多个内核。否则,它将在16核心系统上编译另一个文件。这意味着您只需将构建选项更改一行就可以使其编译速度提高16倍。