跳转到内容

LLVM 编译器/OpenMP 支持

来自维基教科书,一个开放的世界中的开放书籍

随着 Clang 3.8.0 的发布,OpenMP 3.1 支持在 Clang 中默认启用,因此 OpenMP 运行时作为 Clang 构建的正常部分构建,并与二进制分发版一起分发。因此,您不需要明确签出此代码,或在树外构建它;正常的 Clang 签出和构建将自动包含构建这些运行时库。

https://openmp.llvm.org/


cmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$LLVM_PATH -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;compiler-rt;openmp" -DCLANG_BUILD_EXAMPLES=1 $LLVM_SRC/llvm

ninja install -j8 -l8

OpenMP 降低或代码生成

[编辑 | 编辑源代码]

Hello 示例

[编辑 | 编辑源代码]
cat omp_hello.c 
#include <omp.h>
#include <stdio.h>

int main (int argc, char *argv[]) 
{
  int nthreads, tid;

#pragma omp parallel private(nthreads, tid)
  {

    tid = omp_get_thread_num();
    printf("Hello World from thread = %d\n", tid);
  } 

}

clang -fopenmp -S -O3 -emit-llvm omp_hello.c

cat omp_hello.ll

 1 ; ModuleID = 'omp_hello.c'
  2 source_filename = "omp_hello.c"
  3 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
  4 target triple = "x86_64-unknown-linux-gnu"
  5 
  6 %struct.ident_t = type { i32, i32, i32, i32, i8* }
  7 
  8 @.str = private unnamed_addr constant [30 x i8] c"Hello World from thread = %d\0A\00", align 1
  9 @.str.1 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
 10 @0 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i32 0, i32 0) }, align 8
 11 
 12 ; Function Attrs: nounwind uwtable
 13 define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 {
 14 entry:
 15   tail call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*,     i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) #4
 16   ret i32 0
 17 }
 18 
 19 ; Function Attrs: norecurse nounwind uwtable
 20 define internal void @.omp_outlined.(i32* noalias nocapture readnone %.global_tid., i32* noalias nocapture readnone %.bound_tid.) #1 {
 21 entry:
 22   %call = tail call i32 @omp_get_thread_num() #4
 23   %call1 = tail call i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1) getelementptr inbounds ([30 x i8], [30 x i8]* @.str, i64 0, i64 0), i32 %call)
 24   ret void
 25 }
 26 
 27 declare dso_local i32 @omp_get_thread_num() local_unnamed_addr #2
 28 
 29 ; Function Attrs: nofree nounwind
 30 declare dso_local i32 @printf(i8* nocapture readonly, ...) local_unnamed_addr #3
 31 
 32 declare !callback !2 dso_local void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) local_unnamed_addr

卸载示例

[编辑 | 编辑源代码]
#include <stdio.h>
#include <omp.h>

int main(void) {
  int isHost = 0;

#pragma omp target map(from: isHost)
  { isHost = omp_is_initial_device(); }

  if (isHost < 0) {
    printf("Runtime error, isHost=%d\n", isHost);
  }

  // CHECK: Target region executed on the device
  printf("Target region executed on the %s\n", isHost ? "host" : "device");

  return isHost;
}

clang -fopenmp -S -O3 -emit-llvm -fopenmp-targets=nvptx64-nvidia-cuda offloading_success.cpp

相关源文件

[编辑 | 编辑源代码]

列表

  • 测试:clang/test/OpenMP
  • 用于 OpenMP IR 的 Clang 代码生成
    • clang/lib/CodeGen/CGOpenMPRuntime.cpp
    • clang/lib/CodeGen/CGStmtOpenMP.cpp // 此文件包含将 OpenMP 节点作为 LLVM 代码发出代码。
  • LLVM OMP IR 生成器:llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
  • 运行时支持:openmp/runtime/src/kmp_csupport.cpp

如何调试

[编辑 | 编辑源代码]

首先,使用 -v 来显示 clang 驱动程序使用的实际命令行

clang -v -fopenmp omp_hello.c

clang version 10.0.1 (https://github.com/llvm/llvm-project d24d5c8e308e689dcd83cbafd2e8bd32aa845a15)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/ubuntu/install/llvm_install/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;@m64
Selected multilib: .;@m64

/home/ubuntu/install/llvm_install/bin/clang-10 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name omp_hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /home/ubuntu/install/llvm_install/lib/clang/10.0.1 -internal-isystem /usr/local/include -internal-isystem /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/ubuntu -ferror-limit 19 -fmessage-length 0 -fopenmp -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/omp_hello-c73985.o -x c omp_hello.c


clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
 "/usr/bin/ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0 -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../.. -L/home/ubuntu/install/llvm_install/bin/../lib -L/lib -L/usr/lib /tmp/omp_hello-c73985.o -lomp -lgcc --as-needed -lgcc_s --no-as-needed -lpthread -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/7.5.0/crtend.o /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../x86_64-linux-gnu/crtn.o


接下来,使用 gdb 来调试具有完整命令行选项的实际可执行文件

  • gdb -args /home/ubuntu/install/llvm_install/bin/clang-10 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name omp_hello.c -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /home/ubuntu/install/llvm_install/lib/clang/10.0.1 -internal-isystem /usr/local/include -internal-isystem /home/ubuntu/install/llvm_install/lib/clang/10.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /home/ubuntu -ferror-limit 19 -fmessage-length 0 -fopenmp -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o /tmp/omp_hello-c73985.o -x c omp_hello.c

在 gdb 中对编译器进行热身运行

  • (gdb) r

在 1829 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) 处设置断点

  • b CGOpenMPRuntime.cpp:1829
  • r # 运行它

现在可以检查回溯/调用堆栈

Breakpoint 1, clang::CodeGen::CGOpenMPRuntime::createRuntimeFunction (this=0x555565d75fd0, Function=0)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:1829
1829	llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
(gdb) bt
#0  clang::CodeGen::CGOpenMPRuntime::createRuntimeFunction (this=0x555565d75fd0, Function=0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:1829
#1  0x000055555af54a62 in clang::CodeGen::CGOpenMPRuntime::<lambda(clang::CodeGen::CodeGenFunction&, clang::CodeGen::PrePostActionTy&)>::operator()(clang::CodeGen::CodeGenFunction &, clang::CodeGen::PrePostActionTy &) const (__closure=0x7fffffff80a0, CGF=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:3109
#2  0x000055555af89801 in clang::CodeGen::RegionCodeGenTy::CallbackFn<clang::CodeGen::CGOpenMPRuntime::emitParallelCall(clang::CodeGen::CodeGenFunction&, clang::SourceLocation, llvm::Function*, llvm::ArrayRef<llvm::Value*>, const clang::Expr*)::<lambda(clang::CodeGen::CodeGenFunction&, clang::CodeGen::PrePostActionTy&)> >(intptr_t, clang::CodeGen::CodeGenFunction &, clang::CodeGen::PrePostActionTy &) (CodeGen=140737488322720, CGF=..., Action=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.h:76
#3  0x000055555af45212 in clang::CodeGen::RegionCodeGenTy::operator() (this=0x7fffffff8080, CGF=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:787
#4  0x000055555af55072 in clang::CodeGen::CGOpenMPRuntime::emitParallelCall (this=0x555565d75fd0, CGF=..., Loc=..., OutlinedFn=0x555565d0bf78, CapturedVars=..., IfCond=0x0)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGOpenMPRuntime.cpp:3145
#5  0x000055555aabd108 in emitCommonOMPParallelDirective (CGF=..., S=..., InnermostKind=llvm::omp::Directive::OMPD_parallel, CodeGen=..., CodeGenBoundParameters=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmtOpenMP.cpp:1329
#6  0x000055555aabdbbf in clang::CodeGen::CodeGenFunction::EmitOMPParallelDirective (this=0x7fffffff8880, S=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmtOpenMP.cpp:1439
#7  0x000055555aa94671 in clang::CodeGen::CodeGenFunction::EmitStmt (this=0x7fffffff8880, S=0x555565e22980, Attrs=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmt.cpp:193
#8  0x000055555aa95392 in clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope (this=0x7fffffff8880, S=..., GetLast=false, AggSlot=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CGStmt.cpp:444
#9  0x000055555ab1ff79 in clang::CodeGen::CodeGenFunction::EmitFunctionBody (this=0x7fffffff8880, Body=0x555565e229b8)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenFunction.cpp:1146
#10 0x000055555ab20be3 in clang::CodeGen::CodeGenFunction::GenerateCode (this=0x7fffffff8880, GD=..., Fn=0x555565d0bd38, FnInfo=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenFunction.cpp:1311
#11 0x000055555ab498d0 in clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition (this=0x555565d73210, GD=..., GV=0x555565d0bd38)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:4474
#12 0x000055555ab42709 in clang::CodeGen::CodeGenModule::EmitGlobalDefinition (this=0x555565d73210, GD=..., GV=0x0)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:2864
#13 0x000055555ab4123f in clang::CodeGen::CodeGenModule::EmitGlobal (this=0x555565d73210, GD=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:2567
#14 0x000055555ab4d9a0 in clang::CodeGen::CodeGenModule::EmitTopLevelDecl (this=0x555565d73210, D=0x555565e20f20)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenModule.cpp:5279
#15 0x000055555baa4537 in (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl (this=0x555565d72870, DG=...)
    at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/ModuleBuilder.cpp:170
#16 0x000055555ba9de7a in clang::BackendConsumer::HandleTopLevelDecl (this=0x555565d72690, D=...) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenAction.cpp:214
#17 0x000055555cf95464 in clang::ParseAST (S=..., PrintStats=false, SkipFunctionBodies=false) at /home/ubuntu/source/llvm_src/clang/lib/Parse/ParseAST.cpp:162
#18 0x000055555b1ba873 in clang::ASTFrontendAction::ExecuteAction (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/FrontendAction.cpp:1043
#19 0x000055555ba9bd46 in clang::CodeGenAction::ExecuteAction (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/CodeGen/CodeGenAction.cpp:1179
#20 0x000055555b1ba1d4 in clang::FrontendAction::Execute (this=0x555565d52ac0) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/FrontendAction.cpp:936
#21 0x000055555b14eb74 in clang::CompilerInstance::ExecuteAction (this=0x555565d4f490, Act=...) at /home/ubuntu/source/llvm_src/clang/lib/Frontend/CompilerInstance.cpp:965
#22 0x000055555b325e07 in clang::ExecuteCompilerInvocation (Clang=0x555565d4f490) at /home/ubuntu/source/llvm_src/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:290
#23 0x0000555557d60900 in cc1_main (Argv=..., Argv0=0x7fffffffe2fb "/home/ubuntu/install/llvm_install/bin/clang-10", 
    MainAddr=0x555557d541aa <GetExecutablePath[abi:cxx11](char const*, bool)>) at /home/ubuntu/source/llvm_src/clang/tools/driver/cc1_main.cpp:240
#24 0x0000555557d55a4c in ExecuteCC1Tool (ArgV=...) at /home/ubuntu/source/llvm_src/clang/tools/driver/driver.cpp:329
#25 0x0000555557d561ca in main (argc_=54, argv_=0x7fffffffdef8) at /home/ubuntu/source/llvm_src/clang/tools/driver/driver.cpp:403

华夏公益教科书