Skip to content

Commit

Permalink
Add demo for vector forward mode
Browse files Browse the repository at this point in the history
  • Loading branch information
vaithak committed Aug 6, 2023
1 parent e685e2b commit 0edc12c
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/clang-tidy-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
id: review
with:
build_dir: build
exclude: "test/*,benchmark/*"
exclude: "test/*,benchmark/*,demos/*"
split_workflow: true
cmake_command: >
pip install cmake lit &&
Expand Down
52 changes: 52 additions & 0 deletions demos/VectorForwardMode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//--------------------------------------------------------------------*- C++ -*-
// clad - The C++ Clang-based Automatic Differentiator
//
// A demo, describing how to use vector forward mode AD to differentiation
// a function with respect to multiple parameters.
//----------------------------------------------------------------------------//

// To run the demo please type:
// path/to/clang++ -Xclang -add-plugin -Xclang clad -Xclang -load -Xclang \
// path/to/libclad.so -I../include/ -x c++ -std=c++11 VectorForwardMode.cpp
//
// A typical invocation would be:
// ../../../../obj/Debug+Asserts/bin/clang++ -Xclang -add-plugin -Xclang clad \
// -Xclang -load -Xclang ../../../../obj/Debug+Asserts/lib/libclad.dylib \
// -I../include/ -x c++ -std=c++11 VectorForwardMode.cpp

// Necessary for clad to work include
#include "clad/Differentiator/Differentiator.h"

// A function for weighted sum of array elements.
double weighted_sum(double* arr, double* weights, int n) {
double res = 0;
for (int i = 0; i < n; ++i) {
res += weights[i] * arr[i];
}
return res;
}

int main() {
auto weighted_sum_grad =
clad::differentiate<clad::opts::vector_mode>(weighted_sum, "arr,weights");

// Initialize array and weights.
double arr[3] = {3.0, 4.0, 5.0};
double weights[3] = {0.5, 0.7, 0.9};

// Allocate memory for derivatives.
double d_arr[3] = {0.0, 0.0, 0.0};
double d_weights[3] = {0.0, 0.0, 0.0};
clad::array_ref<double> d_arr_ref(d_arr, 3);
clad::array_ref<double> d_weights_ref(d_weights, 3);

// Calculate gradient.
weighted_sum_grad.execute(arr, weights, 3, d_arr_ref, d_weights_ref);
printf("Vector forward mode w.r.t. all:\n darr = {%.2g, %.2g, %.2g}\n "
"dweights = "
"{%.2g, %.2g, %.2g}\n",
d_arr[0], d_arr[1], d_arr[2], d_weights[0], d_weights[1],
d_weights[2]);

return 0;
}
22 changes: 11 additions & 11 deletions lib/Differentiator/VectorForwardModeVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ VectorForwardModeVisitor::DeriveVectorMode(const FunctionDecl* FD,
// Create an identity matrix for the parameter,
// with number of rows equal to the size of the array,
// and number of columns equal to the number of independent variables
llvm::SmallVector<Expr*> args = {getSize, m_IndVarCountExpr,
offsetExpr};
llvm::SmallVector<Expr*, 3> args = {getSize, m_IndVarCountExpr,
offsetExpr};
dVectorParam = BuildCallExprToCladFunction("identity_matrix", args,
{dParamType}, loc);

Expand All @@ -160,7 +160,7 @@ VectorForwardModeVisitor::DeriveVectorMode(const FunctionDecl* FD,
}
} else {
// Create a one hot vector for the parameter.
llvm::SmallVector<Expr*> args = {m_IndVarCountExpr, offsetExpr};
llvm::SmallVector<Expr*, 2> args = {m_IndVarCountExpr, offsetExpr};
dVectorParam = BuildCallExprToCladFunction("one_hot_vector", args,
{dParamType}, loc);
++nonArrayIndVarCount;
Expand Down Expand Up @@ -444,21 +444,21 @@ StmtDiff VectorForwardModeVisitor::VisitArraySubscriptExpr(
std::transform(std::begin(Indices), std::end(Indices),
std::begin(clonedIndices),
[this](const Expr* E) { return Clone(E); });
auto cloned = BuildArraySubscript(clonedBase, clonedIndices);
auto* cloned = BuildArraySubscript(clonedBase, clonedIndices);

QualType ExprTy = ASE->getType();
if (ExprTy->isPointerType())
ExprTy = ExprTy->getPointeeType();

Check warning on line 451 in lib/Differentiator/VectorForwardModeVisitor.cpp

View check run for this annotation

Codecov / codecov/patch

lib/Differentiator/VectorForwardModeVisitor.cpp#L451

Added line #L451 was not covered by tests
auto zero = ConstantFolder::synthesizeLiteral(ExprTy, m_Context, 0);
auto* zero = ConstantFolder::synthesizeLiteral(ExprTy, m_Context, 0);
Expr* diffExpr = zero;

Expr* target = BaseDiff.getExpr_dx();
if (target) {
diffExpr =
m_Sema
.ActOnArraySubscriptExpr(getCurrentScope(), target,
target->getExprLoc(), clonedIndices, noLoc)
.get();
diffExpr = m_Sema
.ActOnArraySubscriptExpr(getCurrentScope(), target,
target->getExprLoc(),
clonedIndices.front(), noLoc)
.get();
}
return StmtDiff(cloned, diffExpr);
}
Expand Down Expand Up @@ -515,7 +515,7 @@ StmtDiff VectorForwardModeVisitor::VisitReturnStmt(const ReturnStmt* RS) {
Expr* getSize = BuildArrayRefSizeExpr(dParam);

// Create an expression to fetch slice of the return vector.
llvm::SmallVector<Expr*> args = {offsetExpr, getSize};
llvm::SmallVector<Expr*, 2> args = {offsetExpr, getSize};
dParamValue = BuildArrayRefSliceExpr(dVectorRef, args);

// Update the array independent expression.
Expand Down
30 changes: 30 additions & 0 deletions test/Misc/RunDemos.C
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,33 @@
// CHECK_ARRAYS_EXEC: {0, 0, 0}
// CHECK_ARRAYS_EXEC: {0, 0, 0}
// CHECK_ARRAYS_EXEC: {0, 0, 0}

//-----------------------------------------------------------------------------/
// Demo: VectorForwardMode.cpp
//-----------------------------------------------------------------------------/
// RUN: %cladclang %S/../../demos/VectorForwardMode.cpp -I%S/../../include -oVectorForwardMode.out 2>&1 | FileCheck -check-prefix CHECK_VECTOR_FORWARD_MODE %s
// CHECK_VECTOR_FORWARD_MODE: void weighted_sum_dvec_0_1(double *arr, double *weights, int n, clad::array_ref<double> _d_arr, clad::array_ref<double> _d_weights) {
// CHECK_VECTOR_FORWARD_MODE-NEXT unsigned long indepVarCount = _d_arr.size() + _d_weights.size();
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::matrix<double> _d_vector_arr = clad::identity_matrix(_d_arr.size(), indepVarCount, 0UL);
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::matrix<double> _d_vector_weights = clad::identity_matrix(_d_weights.size(), indepVarCount, _d_arr.size());
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array<int> _d_vector_n = clad::zero_vector(indepVarCount);
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array<double> _d_vector_res(clad::array<double>(indepVarCount, 0));
// CHECK_VECTOR_FORWARD_MODE-NEXT double res = 0;
// CHECK_VECTOR_FORWARD_MODE-NEXT {
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array<int> _d_vector_i(clad::array<int>(indepVarCount, 0));
// CHECK_VECTOR_FORWARD_MODE-NEXT for (int i = 0; i < n; ++i) {
// CHECK_VECTOR_FORWARD_MODE-NEXT _d_vector_res += (_d_vector_weights[i]) * arr[i] + weights[i] * (_d_vector_arr[i]);
// CHECK_VECTOR_FORWARD_MODE-NEXT res += weights[i] * arr[i];
// CHECK_VECTOR_FORWARD_MODE-NEXT }
// CHECK_VECTOR_FORWARD_MODE-NEXT }
// CHECK_VECTOR_FORWARD_MODE-NEXT {
// CHECK_VECTOR_FORWARD_MODE-NEXT clad::array<double> _d_vector_return(clad::array<double>(indepVarCount, _d_vector_res));
// CHECK_VECTOR_FORWARD_MODE-NEXT _d_arr = _d_vector_return.slice(0UL, _d_arr.size());
// CHECK_VECTOR_FORWARD_MODE-NEXT _d_weights = _d_vector_return.slice(_d_arr.size(), _d_weights.size());
// CHECK_VECTOR_FORWARD_MODE-NEXT return;
// CHECK_VECTOR_FORWARD_MODE-NEXT }
// CHECK_VECTOR_FORWARD_MODE-NEXT }
// RUN: ./VectorForwardMode.out | FileCheck -check-prefix CHECK_VECTOR_FORWARD_MODE_EXEC %s
// CHECK_VECTOR_FORWARD_MODE_EXEC: Vector forward mode w.r.t. all:
// CHECK_VECTOR_FORWARD_MODE_EXEC: darr = {0.5, 0.7, 0.9}
// CHECK_VECTOR_FORWARD_MODE_EXEC: dweights = {3, 4, 5}

0 comments on commit 0edc12c

Please sign in to comment.