diff --git a/1_square/Makefile b/1_square/Makefile index c223268..ac857c5 100644 --- a/1_square/Makefile +++ b/1_square/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran build once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 3.14 diff --git a/1_square/square.f90 b/1_square/square.f90 new file mode 100644 index 0000000..a3acba7 --- /dev/null +++ b/1_square/square.f90 @@ -0,0 +1,24 @@ +program main + use enzyme, only: enzyme_autodiff + implicit none + real :: x, y, dy + + ! Evaluate the function for some arbitrary input + x = 3.0 + y = square(x) + write(*, "('square(',f0.0,')=',f0.0)") x, y + + ! Evaluate its derivative using reverse mode + dy = 0.0 + call enzyme_autodiff(square, x, dy) + write(*, "('Gradient square(',f0.0,')=',f0.0)") x, dy + + contains + + ! Function we seek to differentiate + real function square(x) + real, intent(in) :: x + square = x ** 2 + end function + +end program diff --git a/2_norm/Makefile b/2_norm/Makefile index 3229d2a..9b9cf44 100644 --- a/2_norm/Makefile +++ b/2_norm/Makefile @@ -15,5 +15,7 @@ clean: %.o: %.ll ../dockerscript.sh clang-12 -O2 /host/$^ -o /host/$@ -lm +# TODO: Fortran builds once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 2000 diff --git a/2_norm/norm.f90 b/2_norm/norm.f90 new file mode 100644 index 0000000..2e89c35 --- /dev/null +++ b/2_norm/norm.f90 @@ -0,0 +1,43 @@ +program main + use enzyme, only: enzyme_const, enzyme_dup, enzyme_autodiff + implicit none + integer, parameter :: n = 1000000 + integer, parameter :: initial_value = 20 + real :: x(n), dx(n) + real :: y(n), dy(n) + real :: start, finish, time + + ! Fill the input array with an arbitrary value + x(:) = initial_value + + ! Time the primal computation + call cpu_time(start) + call norm(n, x, y) + call cpu_time(finish) + time = finish - start + write(*, "('Serial normalize ',f0.6,1x,es11.4)") time, y(n) + + ! Zero the gradients and specify the seed + dx(:) = 0.0 + dy(:) = 1.0 + + ! Time the reverse mode computation + call cpu_time(start) + call enzyme_autodiff(norm, enzyme_const, n, & + enzyme_dup, x, dx, & + enzyme_dup, y, dy) + call cpu_time(finish) + time = finish - start + write(*, "('Gradient normalize ',f0.6,2(1x,es11.4))") time, y(n), dx(1) + +contains + + ! Function we seek to differentiate + subroutine norm(n, x, y) + integer, intent(in) :: n + real, dimension(n), intent(in) :: x + real, dimension(n), intent(out) :: y + y(:) = x / sum(x) + end subroutine + +end program diff --git a/3_dot/Makefile b/3_dot/Makefile index 5c88940..922a57f 100644 --- a/3_dot/Makefile +++ b/3_dot/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran builds once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ diff --git a/3_dot/dot.f90 b/3_dot/dot.f90 new file mode 100644 index 0000000..db3bfd5 --- /dev/null +++ b/3_dot/dot.f90 @@ -0,0 +1,57 @@ +program main + use enzyme, only: enzyme_const, enzyme_dup, enzyme_autodiff + implicit none + + integer, parameter :: n = 20000000 + integer, parameter :: x = 20 + real :: a(n), b(n), c = 1 / x + real :: da(n), db(n), dc + real :: start, finish, time + integer :: i, dn + + ! Specify input + do i = 1, n + a(i) = x / i + b(i) = x + i - 1 ! NOTE: Minus one to account for 1-indexing + end do + + ! Time gradient computation with respect to all variables (A, B, and C) + da(:) = 0.0 + db(:) = 0.0 + dc = 0.0 + call cpu_time(start) + call enzyme_autodiff(dot, enzyme_const, n, & + enzyme_dup, a, da, & + enzyme_dup, b, db, & + enzyme_dup, c, dc) + call cpu_time(finish) + time = finish - start + write(*, "('Grad Normalize time=',f0.6)", advance="no") time + write(*, "(' A`(1)=',f4.1,' B`(1)=',f4.1,' C`=',f4.1)") da(1), db(1), dc + + ! Time gradient computation with respect to just B + da(:) = 0.0 + db(:) = 0.0 + dc = 0.0 + call cpu_time(start) + call enzyme_autodiff(dot, enzyme_const, n, & + enzyme_const, a, & + enzyme_dup, b, db, & + enzyme_const, c) + call cpu_time(finish) + time = finish - start + write(*, "('Constant A time=',f0.6)", advance="no") time + write(*, "(' A`(1)=',f4.1,' B`(1)=',f4.1,' C`=',f4.1)") da(1), db(1), dc + +contains + + ! Function we seek to differentiate + real function dot(n, x, y, z) + integer, intent(in) :: n + real, dimension(n), intent(in) :: x + real, dimension(n), intent(in) :: y + real, intent(in) :: z + dot = dot_product(x, y) + z + end function + +end program diff --git a/7_fwd/Makefile b/7_fwd/Makefile index 3d78be1..710aa14 100644 --- a/7_fwd/Makefile +++ b/7_fwd/Makefile @@ -6,5 +6,7 @@ clean: %.o: %.c ../dockerscript.sh clang-12 /host/$^ -O3 -Xclang -load -Xclang /Enzyme/enzyme/build/Enzyme/ClangEnzyme-12.so -ffast-math -o /host/$@ +# TODO: Fortran build once Flang plugin available + run-%: %.o ../dockerscript.sh /host/$^ 3.14 diff --git a/7_fwd/fwd.f90 b/7_fwd/fwd.f90 new file mode 100644 index 0000000..ea58200 --- /dev/null +++ b/7_fwd/fwd.f90 @@ -0,0 +1,37 @@ +program main + use enzyme, only: enzyme_fwddiff + implicit none + + real :: a, b, c + real :: da, db, dc + + ! Specify input + a = 2.0 + b = 3.0 + + ! Specify seeds + da = 1.0 + db = 1.0 + + ! Compute forward mode derivative + call enzyme_fwddiff(my_loop, a, da, b, db, c, dc) + write(unit=6, fmt="(' a=',f2.0,' b=',f2.0,' c=',f4.0)") a, b, c + write(unit=6, fmt="(' da=',f2.0,' db=',f2.0,' dc=',f4.0)") da, db, dc + +contains + + ! Function we seek to evaluate + subroutine my_loop(x, y, z) + real, intent(in) :: x + real, intent(in) :: y + real, intent(out) :: z + real :: s + integer :: i + s = 0.0 + do i = 1, 100 + s = s + x + y + end do + z = s + end subroutine + +end program