调研了RAJA库的简单使用
RAJA简介
RAJA 是由LLNL开发的一个 C++ 抽象软件库,旨在为高性能计算(HPC)应用实现架构和编程模型的可移植性。RAJA 有两个主要目标:
- 使应用程序的移植性得到实现,同时将对现有算法和编程风格的干扰降至可控范围。
- 实现与直接使用常见编程模型(例如 OpenMP、CUDA 等)相当的性能。
RAJA 通过提供扩展了普遍接受的并行 for 语句的构建模块,来实现可移植的并行循环执行。
RAJA 帮助开发者将应用程序的循环内核与底层架构和特定于编程模型的实现细节隔离开来。循环体和循环执行通过 C++ lambda表达式和 C++ 模板解耦。这种方法促进了应用开发者应该尽可能专注于调优循环模式而非单个循环的观点。RAJA 使得通过执行策略类型对应用程序进行参数化相对简单,从而可以针对特定架构配置进行编译。
简单来说,RAJA是一个兼容层,类似OpenACC,但是在代码转换后直接转化为原生的OpenMP、CUDA、ROCm,暂不支持MPI
RAJA的依赖
RAJA使用CUB CUDA utilities library来使代码运行在CUDA上
RAJA使用rocPRIM HIP parallel primitives library来使代码运行在ROCm上
RAJA的简单使用
简单加速循环
并行加速的主要加速对象就是一个for循环,对于一个简单的循环,可用使用以下代码进行加速
for (int i = 0; i < N; ++i) {
c[i] = a[i] + b[i];
}
可以使用RAJA表达为:
//seq_exec 串行策略
//omp_parallel_for_exec OpenMP策略
//cuda_exec CUDA策略
//hip_exec HIP策略
RAJA::forall<exec_policy>(RAJA::TypesRangeSegment<int>(0, N), [=] (int i) {
c[i] = a[i] + b[i];
});
较为复杂的循环
for (int iN = 0; iN < NN; ++iN) {
...
for (int i0 = 0; i0 < N0; ++i0) {s
\\ inner loop body
}
}
对于一个二级嵌套循环,RAJA不希望使用RAJA::forall的嵌套,他提供了另外一种方法
RAJA::kernel<RAJA::KernelPolicy<
RAJA::statement::For<0, RAJA::omp_parallel_for_exec, // 外循环使用 OpenMP 并行
RAJA::statement::For<1, RAJA::seq_exec> // 内循环使用串行执行
> >>(RAJA::make_tuple(RAJA::RangeSegment(0, N),
RAJA::RangeSegment(0, M)),
[=](int i, int j) {
array[i][j] = array[i][j] * 2;
});