简化的网格计算:使用 XGE 加速顺序进程






3.60/5 (6投票s)
许多常规流程,如单元测试脚本、构建等,仍然需要过长的时间来执行。本文介绍了如何通过将复杂的构建、脚本和自定义应用程序转换为分布式、并行进程来加速它们的执行。
引言
即使如今更快的、多核处理器越来越普及,软件开发周期中许多日常的计算过程仍然耗时过长。在一个典型的中大型软件项目中,下面列出的某个进程最终成为开发流水线中的一个主要瓶颈,耗时数十分钟甚至数小时,这是很常见的。
- 代码构建
- 静态代码分析
- 单元测试脚本
- 数据/资源构建
- 代码生成
- 打包和压缩
- 仿真
- 其他自定义串行进程
下文将演示如何通过利用 IncrediBuild(来自 Xoreax Software 的分布式构建环境)最近添加的 XGE Interfaces 扩展包,将这些进程分发到本地网络中的机器上执行,从而轻松加速它们。
串行进程的 Grid 化
上述进程的共同点在于它们都传统上是顺序执行的。无论使用何种技术来执行这些进程(常见示例包括脚本语言、make 变体、第三方专用应用程序和内部工具),它们都具有相同的局限性,即必须在启动机器有限的 CPU 和内存资源下运行(有些工具允许有限的并行性,通过利用多个核心/CPU,但即使这种方法也受限于在单台机器上运行的基本局限性)。
一个进程如果满足两个基本要求,就可以被认为是 Grid 化(“Grid Computing”是并行、网络化执行复杂进程的通用术语)的良好候选者。
- 它必须由一组理论上可以并行运行的命令组成。换句话说,应该有一大部分命令不被强制顺序执行的依赖关系所约束。
- 要分发的命令应该是计算密集型的,这样才能最有效地分发。
加速满足上述标准的进程,首先需要定义哪些任务的执行应该分发到远程机器。完成之后,我们的分布式执行环境需要能够可靠地在远程机器上执行命令,将输出收集回启动机器,处理各种断开/错误场景,最重要的是——无论启动机器和远程机器之间存在任何环境差异,都要保证最终结果始终有效。
Xoreax Grid Engine
XGE 是 IncrediBuild 的技术核心,IncrediBuild 是一个商业产品,利用 Grid Computing 来加速 Visual Studio 构建。最近 Xoreax Software 发布了一套新的接口,允许使用 XGE 通过分布式处理轻松加速许多复杂的 Windows 进程。XGE 的一个独特之处在于它能够在一个特殊的受保护的虚拟环境中远程机器上执行分布式命令,该环境完全模拟了启动机器的环境。例如,如果一个分布式编译过程将一个源文件发送到远程机器进行编译,那么编译过程就必须像在启动机器上一样精确地运行。同样重要的是,远程机器的环境必须保持“受保护”,不受分布式命令所做的任何修改的影响——因为自然,对文件或环境的任何修改都应该只影响启动机器的环境。
XGE 的虚拟环境会自动复制启动节点的环境和文件系统,导致在其内部执行的命令始终访问启动节点的环境和文件系统,同时利用远程节点自身的 CPU 和内存资源。在远程节点上执行的任务同样不能修改远程节点的文件系统或注册表。相反,对文件系统的任何修改都会被传输到启动节点,从而保证了分布式进程的完整性,同时保持远程节点的环境不受影响。
使用 XGE 需要安装“IncrediBuild Agent”——一个轻量级的客户端组件,能够发起和参与分布式进程。它可以安装在任何用户工作站上,不需要专用服务器。有关 XGE Grid 技术和架构的更多信息,请参阅 此页面。

XGE Monitor 提供了对分布式过程的清晰可视化表示。
示例
以下是两个使用 IncrediBuild XGE Interfaces 将现有进程转换为分布式、并行解决方案的示例。这些示例假定在启动机器上已安装 IncrediBuild Agent。
- 加速基于脚本的单元测试过程
在本例中,我们将通过 3 个简单步骤,使用 XGE Submission 接口,了解如何将现有脚本转换为并行、分布式解决方案。 - 加速基于 make 的构建
本示例描述了如何通过 XGE Automatic Interception 接口加速一个基于 gmake 的进程,而无需修改 makefile(相同的技术可以应用于各种 make 工具)。
示例 #1 - 加速基于脚本的单元测试过程
本例中的场景涉及一个常规运行的脚本,该脚本针对不同的输入数据集执行一个控制台应用程序,以验证是否获得了预期的输出。这种场景的变体非常普遍,执行技术从不同的脚本语言到专用的商业产品都有。在这个简单的例子中,我们将假设进程通过一组 .bat 文件进行控制。
我们的示例脚本的执行可以概述为以下几个阶段:
- 通过调用脚本 Utest.bat 来启动进程。
- 脚本通过运行各种工具和文件复制来准备输入文件。
- 脚本通过调用控制台应用程序 URun.exe 来运行实际的单元测试,每次使用不同的输入参数集。
- 脚本运行另一个工具,该工具将第 3 步中创建的输出文件与预先构建的“预期结果”文件集进行比较,并报告任何差异,表明潜在问题。
通常,第 3 步会成为这类进程的瓶颈,因为它基本上会一遍又一遍地循环,直到处理完所有输入数据。因此,对这一特定阶段进行 Grid 化将带来最显著的性能提升。
使用 XGE Submission Interface,转换为分布式、并行进程将涉及对我们进程的以下更改:
更改 #1:将命令提交到 XGE 队列
对 URun.exe(或我们希望分发的任何工具)的调用将替换为对 Submission Interface 工具的调用。例如,如果脚本中的相关行如下所示:
Call URun.exe -run "%1" -o "%2%.out"
修改后的版本将是:
Call xgSubmit.exe /group="URunTests" # URun.exe -run "%1" -o "%2%.out"
每当运行修改后的行时,原始命令(在 #
字符之后指定)将被排队等待分布式执行,并分配一个逻辑名称 URunTests
。控制将立即返回脚本,无论命令是否已实际开始执行。这使得我们能够在像 *.bat 脚本这样的本质上是顺序的环境中实现并行执行。
更改 #2:在访问结果之前暂停脚本执行
就在进程实际使用分布式命令的输出文件之前,我们必须等待该命令完成。在我们的例子中,在运行第 4 步中的最终验证过程之前,我们将希望等待所有已排队的命令完成执行。我们通过以下命令来实现这一点:
xgWait.exe /group="URunTests"
这将暂停脚本,直到通过 xgSubmit.exe 以逻辑名称 URunTests
提交的所有命令都已完全完成,并且所有输出文件都已同步并写入磁盘。当然,如果此时所有相关命令都已经执行完毕,我们的脚本将继续执行。
更改 #3:通过 XGE 执行我们的脚本
最后一步是通过 XGE 引擎执行我们的脚本以激活分布式执行。因此,第 1 步将更改为:
xgConsole.exe /command="Utest.bat"
我们的单元测试脚本执行现在已分发到网络上,实现了 X5-X10 的加速(具体取决于场景细节)。
示例 #2 - 加速基于 make 的构建
在本例中,我们有一个大型、耗时的基于 GNU gmake 的 makefile 进程(注意:本例中描述的技术也可以应用于常见的构建工具,如 SCONS、ANT、mingw、Clearmake 等)。由于现有的 makefile 源非常复杂,因此最好避免对实际 makefile 进行任何重大修改。幸运的是,XGE 的“Automatic Interception”接口允许您完全 Grid 化基于 make 的进程,而无需修改 makefile。
Automatic Interception XGE 接口利用了许多构建工具的一个特性:能够并行生成多个进程。虽然此特性的目的是利用执行机器上的多个核心和 CPU,但 Automatic Interception 接口利用它将 make 进程的执行分发到网络上,从而实现显著的性能提升。这涉及以下 2 步过程:
更改 #1:准备构建拦截配置文件
在此步骤中,我们创建 XGE 所需的定义文件,以将 gmake 的本地并行执行(通过 -j
命令行参数激活)转换为完全分布式的进程。这是通过一种独特的专利申请中的方法实现的,即监视 make 工具的执行,并将相关的本地工具执行替换为通过 XGE 进行的相应分布式执行。为此,我们创建以下 XML 文件(profile.xml):
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Profile FormatVersion="1">
<Tools>
<Tool Filename="gmake" AllowIntercept="true" />
<Tool Filename="cl" AllowRemote="true" />
<Tool Filename="link" AllowRemote="false" />
</Tools>
</Profile>
我们示例中的 make 进程运行一个典型的代码构建,涉及编译然后链接。上述 XML 定义了以下内容:
- gmake.exe - make 工具可执行文件的名称。
AllowIntercept=True
表示这是 XGE Automatic Interception 接口要监视的进程。 - cl.exe - 编译器工具可执行文件的名称。
AllowRemote=True
表示这是我们有兴趣分发的工具,因为它满足上述分发的两个要求。 - link.exe - 链接器工具可执行文件的名称。由于此工具读取大量 *.obj 文件作为输入且计算量不是很大,因此我们不希望分发其执行,因此设置了
AllowRemote=false
指令。
更改 #2:通过 XGE 执行 make 进程
定义好 profile.xml 文件后,我们就可以通过 XGE 执行 make 进程了。我们将通过 xgConsole.exe 命令行工具运行 gmake,并使用 gmake 的 -j
(多个并行进程)命令行选项。XGE 将监视 gmake 进程,并将任何执行 cl.exe 或 link.exe 的尝试替换为相应的 XGE 任务。通过 XGE 执行 make 进程的语法是:
xgConsole.exe /command="gmake All -j 16" /profile="profile.xml"
-j 16
是 gmake 用于生成多个本地并行进程的命令行参数(16 是任意数字:任何较大的数字都可以,因为 gmake 执行的进程将简单地排队等待通过 XGE 执行)。
完成。我们的 make 进程现在已完全分发到网络上。
其他 XGE 接口
“XGE Interfaces”包提供了另外两个本文未详细介绍的分布式接口:
XML Interface - XML 接口允许使用 XML 文件定义一组命令,每个命令都有输入/输出文件、复杂的依赖关系和其他特性。然后,xgConsole.exe 命令行接口可以对 XML 文件中定义的命令集执行完全或增量构建操作。此接口可用于定义要通过脚本或自定义应用程序执行的复杂分布式进程。
Visual Studio Interface - 通过 Visual Studio 接口,可以将在 Microsoft Visual Studio 项目中定义的自定义步骤、构建事件(预构建、预链接、后构建)和自定义构建规则分发到远程机器。将考虑依赖关系和输出文件定义以确保正确的执行顺序。
摘要
本文介绍了 Grid 化顺序进程的各种技术。希望您觉得 IncrediBuild 的新 XGE Interfaces 扩展包很有用。我们很乐意通过讨论论坛听取您的反馈或问题。
功能齐全、为期 30 天的 IncrediBuild 评估版本(包括 XGE Interfaces 包和分布式 Visual Studio 构建支持)可在此 页面下载。