Skip to content

Commit 49dc18e

Browse files
Shubham Shuklavgvassilev
authored andcommitted
Add reverse mode support for omp parallel directive
1 parent 82308ce commit 49dc18e

3 files changed

Lines changed: 73 additions & 5 deletions

File tree

include/clad/Differentiator/ReverseModeVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ namespace clad {
481481
StmtDiff
482482
VisitOMPParallelForDirective(const clang::OMPParallelForDirective* D);
483483
StmtDiff VisitOMPCriticalDirective(const clang::OMPCriticalDirective* D);
484+
StmtDiff VisitOMPParallelDirective(const clang::OMPParallelDirective* D);
484485

485486
/// Helper function that builds `T* _this = malloc(sifeof(T));`
486487
/// and `free(_this)`.

lib/Differentiator/ReverseModeVisitorOpenMP.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@ StmtDiff ReverseModeVisitor::VisitOMPExecutableDirective(
521521
llvm::SaveAndRestore<bool> SaveisInsideOMPBlock(isInsideOMPBlock);
522522
isInsideOMPBlock = true;
523523

524-
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).ActOnOpenMPRegionStart(OMPD_parallel,
525-
nullptr);
524+
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).ActOnOpenMPRegionStart(
525+
OMPD_parallel, getCurrentScope());
526526
StmtDiff BodyDiff;
527527
{
528528
Sema::CompoundScopeRAII CompoundScope(m_Sema);
@@ -537,8 +537,8 @@ StmtDiff ReverseModeVisitor::VisitOMPExecutableDirective(
537537
.ActOnOpenMPRegionEnd(BodyDiff.getStmt(), OrigClauses)
538538
.get();
539539

540-
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).ActOnOpenMPRegionStart(OMPD_parallel,
541-
nullptr);
540+
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).ActOnOpenMPRegionStart(
541+
OMPD_parallel, getCurrentScope());
542542
// Visit twice, but use only the result of the first visit, for capture
543543
// variables only.
544544
{
@@ -549,7 +549,17 @@ StmtDiff ReverseModeVisitor::VisitOMPExecutableDirective(
549549
const auto* FS = cast<ForStmt>(CS);
550550
DifferentiateCanonicalLoop(FS);
551551
} else {
552-
Visit(CS);
552+
StmtDiff SecondDiff = Visit(CS);
553+
auto& II = m_Context.Idents.get("_clad_reverse_guard");
554+
DeclarationNameInfo CritDirName(DeclarationName(&II), D->getBeginLoc());
555+
llvm::SmallVector<OMPClause*, 0> NoClauses;
556+
Stmt* ProtectedReverse =
557+
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema)
558+
.ActOnOpenMPExecutableDirective(
559+
OMPD_critical, CritDirName, OMPD_unknown, NoClauses,
560+
SecondDiff.getStmt_dx(), D->getBeginLoc(), D->getEndLoc())
561+
.get();
562+
BodyDiff = {BodyDiff.getStmt(), ProtectedReverse};
553563
}
554564
m_Globals.swap(temp);
555565
}
@@ -574,6 +584,15 @@ StmtDiff ReverseModeVisitor::VisitOMPExecutableDirective(
574584
D->getBeginLoc(), D->getEndLoc())
575585
.get()};
576586
}
587+
StmtDiff
588+
ReverseModeVisitor::VisitOMPParallelDirective(const OMPParallelDirective* D) {
589+
DeclarationNameInfo DirName;
590+
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).StartOpenMPDSABlock(
591+
OMPD_parallel, DirName, nullptr, D->getBeginLoc());
592+
StmtDiff SDiff = VisitOMPExecutableDirective(D);
593+
CLAD_COMPAT_CLANG19_SemaOpenMP(m_Sema).EndOpenMPDSABlock(SDiff.getStmt());
594+
return SDiff;
595+
}
577596
StmtDiff ReverseModeVisitor::VisitOMPParallelForDirective(
578597
const OMPParallelForDirective* D) {
579598
DeclarationNameInfo DirName;

test/Gradient/OpenMP.C

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,48 @@ double fn23(const double *x, int n) {
944944
// CHECK-NEXT: }
945945
// CHECK-NEXT: }
946946

947+
double fn24(const double *x, int n) {
948+
double result = 0;
949+
#pragma omp parallel reduction(+:result)
950+
{
951+
result += x[0] * x[1];
952+
result += x[1] * x[2];
953+
result += x[2] * x[3];
954+
}
955+
return result;
956+
}
957+
958+
// CHECK: void fn24_grad(const double *x, int n, double *_d_x, int *_d_n) {
959+
// CHECK-NEXT: double _d_result = 0.;
960+
// CHECK-NEXT: double result = 0;
961+
// CHECK-NEXT: #pragma omp parallel reduction(+: result)
962+
// CHECK-NEXT: {
963+
// CHECK-NEXT: result += x[0] * x[1];
964+
// CHECK-NEXT: result += x[1] * x[2];
965+
// CHECK-NEXT: result += x[2] * x[3];
966+
// CHECK-NEXT: }
967+
// CHECK-NEXT: _d_result += 1;
968+
// CHECK-NEXT: #pragma omp parallel private(result) firstprivate(_d_result)
969+
// CHECK-NEXT: #pragma omp critical (_clad_reverse_guard)
970+
// CHECK-NEXT: {
971+
// CHECK-NEXT: {
972+
// CHECK-NEXT: double _r_d5 = _d_result;
973+
// CHECK-NEXT: _d_x[2] += _r_d5 * x[3];
974+
// CHECK-NEXT: _d_x[3] += x[2] * _r_d5;
975+
// CHECK-NEXT: }
976+
// CHECK-NEXT: {
977+
// CHECK-NEXT: double _r_d4 = _d_result;
978+
// CHECK-NEXT: _d_x[1] += _r_d4 * x[2];
979+
// CHECK-NEXT: _d_x[2] += x[1] * _r_d4;
980+
// CHECK-NEXT: }
981+
// CHECK-NEXT: {
982+
// CHECK-NEXT: double _r_d3 = _d_result;
983+
// CHECK-NEXT: _d_x[0] += _r_d3 * x[1];
984+
// CHECK-NEXT: _d_x[1] += x[0] * _r_d3;
985+
// CHECK-NEXT: }
986+
// CHECK-NEXT: }
987+
// CHECK-NEXT: }
988+
947989
template <size_t N>
948990
void reset(double (&arr)[N], double val = 0) {
949991
for (size_t i = 0; i < N; ++i)
@@ -1067,5 +1109,11 @@ int main() {
10671109
auto fn23_grad = clad::gradient(fn23);
10681110
fn23_grad.execute(x, 4, dx, &dn);
10691111
printf("{%.2f, %.2f, %.2f, %.2f}\n", dx[0], dx[1], dx[2], dx[3]); // CHECK-EXEC: {4.00, 6.00, 8.00, 10.00}
1112+
1113+
omp_set_num_threads(2);
1114+
reset(dx);
1115+
auto fn24_grad = clad::gradient(fn24);
1116+
fn24_grad.execute(x, 4, dx, &dn);
1117+
printf("{%.2f, %.2f, %.2f, %.2f}\n", dx[0], dx[1], dx[2], dx[3]); // CHECK-EXEC: {6.00, 12.00, 16.00, 8.00}
10701118
return 0;
10711119
}

0 commit comments

Comments
 (0)