diff options
4 files changed, 274 insertions, 25 deletions
diff --git a/org.eclipse.photran-samples/Makefile b/org.eclipse.photran-samples/Makefile index 35b9b861..d7c31e73 100644 --- a/org.eclipse.photran-samples/Makefile +++ b/org.eclipse.photran-samples/Makefile @@ -28,7 +28,8 @@ EXEFILES=$(EXEFILE) *.exe all: clean build clean: - for dir in $(SRCDIRS) .; do \ + @echo Cleaning output files + @for dir in $(SRCDIRS) .; do \ cd $$dir; \ rm -f $(OBJFILES) >/dev/null 2>&1; \ rm -f $(OTHERFILES) >/dev/null 2>&1; \ @@ -37,27 +38,31 @@ clean: done build: - @echo "=====>" Using compiler $(FORTRAN) - @for dir in $(SRCDIRS); do \ - if [ -e $$dir/Makefile ]; then \ - $(MAKE) -C $$dir; \ - else \ - echo "=====>" Begin compiling sources in $$dir; \ - $(FORTRAN) $(DEBUGSWITCH) \ - $(OUTSWITCH) $$dir/$(EXEFILE) \ - $(INCLUDESWITCH). \ - $(INCLUDESWITCH)$$dir \ - $(LIBSWITCH). \ - $(LIBSWITCH)$$dir \ - $(OPTSWITCH) \ - $(CRAYSWITCH) \ - $$dir/$(SRCFILES); \ - echo "<=====" Done compiling sources in $$dir; \ - fi \ - done - @for dir in $(SRCDIRS) .; do \ - cd $$dir; \ - rm -f $(OBJFILES) >/dev/null 2>&1; \ - rm -f $(OTHERFILES) >/dev/null 2>&1; \ - cd ..; \ - done + @if [ "$(FORTRAN)" == "" ]; then \ + echo "No Fortran compiler found; cannot compile photran-samples"; \ + else \ + echo "=====>" Using compiler $(FORTRAN); \ + for dir in $(SRCDIRS); do \ + if [ -e $$dir/Makefile ]; then \ + $(MAKE) -C $$dir; \ + else \ + echo "=====>" Begin compiling sources in $$dir; \ + $(FORTRAN) $(DEBUGSWITCH) \ + $(OUTSWITCH) $$dir/$(EXEFILE) \ + $(INCLUDESWITCH). \ + $(INCLUDESWITCH)$$dir \ + $(LIBSWITCH). \ + $(LIBSWITCH)$$dir \ + $(OPTSWITCH) \ + $(CRAYSWITCH) \ + $$dir/$(SRCFILES); \ + echo "<=====" Done compiling sources in $$dir; \ + fi \ + done; \ + for dir in $(SRCDIRS) .; do \ + cd $$dir; \ + rm -f $(OBJFILES) >/dev/null 2>&1; \ + rm -f $(OTHERFILES) >/dev/null 2>&1; \ + cd ..; \ + done; \ + fi diff --git a/org.eclipse.photran-samples/src-liebmann-4-openacc/liebmann.f90 b/org.eclipse.photran-samples/src-liebmann-4-openacc/liebmann.f90 new file mode 100644 index 00000000..e7656f4d --- /dev/null +++ b/org.eclipse.photran-samples/src-liebmann-4-openacc/liebmann.f90 @@ -0,0 +1,103 @@ +!! +!! Liebmann's method to compute heat transfer across a 2-D surface +!! J. Overbey 8/27/08, updated for OpenACC 5/3/12 +!! +!! Use liebmann-viz.sh in the main project directory to visualize the resulting +!! table using gnuplot +!! +!! This version is based on the code in src-liebmann-3-loops, but +!! (1) the "iterate" subroutine is inlined, +!! (2) the number of iterations is always a multiple of 2 (delta is +!! only computed on even-numbered iterations), and +!! (3) with an OpenACC-compliant compiler (e.g., Cray Fortran 8.0), the +!! stencil computations will be moved to an accelerator device/GPU +!! +program liebmann_example + implicit none + + integer, parameter :: SIZE = 4096 + integer, parameter :: INTERIOR_SIZE = SIZE - 2 + integer, parameter :: OUTPUT_SIZE = 128 + real, parameter :: BOUNDARY_VALUE = 5.0 + real, parameter :: EPSILON = 0.001 + + call main() + +contains + +subroutine main() + real :: surface(SIZE, SIZE) + integer :: i, j + + integer :: start_time, end_time, count_rate + + call system_clock(start_time, count_rate) + call liebmann(surface) + call system_clock(end_time) + + do i = 1, SIZE, SIZE/OUTPUT_SIZE + do j = 1, SIZE-1, SIZE/OUTPUT_SIZE + write (*,'(F4.2" ")',advance="no") surface(i, j) + end do + write (*,'(F4.2" ")') surface(i, SIZE) + end do + + print *, "Elapsed Time (seconds):", real(end_time - start_time) / real(count_rate) +end subroutine + +subroutine liebmann(surface) + real, dimension(SIZE, SIZE), intent(out) :: surface + real, dimension(SIZE, SIZE) :: prev, next + real :: delta + integer :: i, j + logical :: done + + call init_with_boundaries(prev) + call init_with_boundaries(next) + + !$acc data copyin(prev,next) copyout(prev) + done = .false. + do while (.not. done) + !$acc parallel loop + do j = 2, SIZE-1 + do i = 2, SIZE-1 + next(i,j) = & + (prev(i-1, j) + & + prev(i+1, j) + & + prev(i, j-1) + & + prev(i, j+1)) / 4.0 + end do + end do + !$acc end parallel loop + delta = 0.0 + !$acc parallel loop reduction(max:delta) + do j = 2, SIZE-1 + do i = 2, SIZE-1 + prev(i,j) = & + (next(i-1, j) + & + next(i+1, j) + & + next(i, j-1) + & + next(i, j+1)) / 4.0 + delta = max(delta, abs(prev(i,j)-next(i,j))) + end do + end do + !$acc end parallel loop + if (delta < EPSILON) then + done = .true. + end if + end do + !$acc end data + surface = prev +end subroutine + +subroutine init_with_boundaries(surface) + real, dimension(SIZE, SIZE), intent(out) :: surface + + surface = 0.0 + surface(1, :) = BOUNDARY_VALUE + surface(SIZE, :) = BOUNDARY_VALUE + surface(:, 1) = BOUNDARY_VALUE + surface(:, SIZE) = BOUNDARY_VALUE +end subroutine + +end program diff --git a/org.eclipse.photran-samples/src-liebmann-5-openmp/Makefile b/org.eclipse.photran-samples/src-liebmann-5-openmp/Makefile new file mode 100644 index 00000000..a0b73c19 --- /dev/null +++ b/org.eclipse.photran-samples/src-liebmann-5-openmp/Makefile @@ -0,0 +1,30 @@ +.PHONY: all clean +SRC=$(wildcard *.f90) + +GFORTRAN=`which gfortran 2>/dev/null | head -1` +IFORT=`which ifort 2>/dev/null | head -1` +DEBUGSWITCH=-g +OPTSWITCH=-O4 +OUTSWITCH=-o + +all: + @if [ "$(GFORTRAN)" != "" ]; then \ + for file in $(SRC); do \ + $(GFORTRAN) -fopenmp \ + $(DEBUGSWITCH) \ + $(OUTSWITCH) `echo $$file | sed -e 's/.f90/.exe/'` \ + $(OPTSWITCH) \ + $$file; \ + done; \ + elif [ "$(IFORT)" != "" ]; then \ + for file in $(SRC); do \ + $(IFORT) -openmp \ + $(DEBUGSWITCH) \ + $(OUTSWITCH) `echo $$file | sed -e 's/.f90/.exe/'` \ + $(OPTSWITCH) \ + $$file; \ + done; \ + fi + +clean: + rm -f *.exe *.mod
\ No newline at end of file diff --git a/org.eclipse.photran-samples/src-liebmann-5-openmp/liebmann.f90 b/org.eclipse.photran-samples/src-liebmann-5-openmp/liebmann.f90 new file mode 100644 index 00000000..1aa2e24d --- /dev/null +++ b/org.eclipse.photran-samples/src-liebmann-5-openmp/liebmann.f90 @@ -0,0 +1,111 @@ +!! +!! Liebmann's method to compute heat transfer across a 2-D surface +!! J. Overbey 8/27/08, updated for OpenMP 5/3/12 +!! +!! Use liebmann-viz.sh in the main project directory to visualize the resulting +!! table using gnuplot +!! +!! This version is based on the code in src-liebmann-4-openacc but uses OpenMP +!! rather than OpenACC. +!! +program liebmann_example + implicit none + + integer, parameter :: SIZE = 4096 + integer, parameter :: INTERIOR_SIZE = SIZE - 2 + integer, parameter :: OUTPUT_SIZE = 128 + real, parameter :: BOUNDARY_VALUE = 5.0 + real, parameter :: EPSILON = 0.001 + + call main() + +contains + +subroutine main() + real :: surface(SIZE, SIZE) + integer :: i, j + integer :: num_threads + integer :: start_time, end_time, count_rate + + call system_clock(start_time, count_rate) + call liebmann(surface, num_threads) + call system_clock(end_time) + + do i = 1, SIZE, SIZE/OUTPUT_SIZE + do j = 1, SIZE-1, SIZE/OUTPUT_SIZE + write (*,'(F4.2" ")',advance="no") surface(i, j) + end do + write (*,'(F4.2" ")') surface(i, SIZE) + end do + + print *, "Threads: ", num_threads + print *, "Elapsed Time (seconds):", real(end_time - start_time) / real(count_rate) +end subroutine + +subroutine liebmann(surface, num_threads) + real, dimension(SIZE, SIZE), intent(out) :: surface + integer, intent(out) :: num_threads + real, dimension(SIZE, SIZE) :: prev, next + real :: delta + integer :: i, j + logical :: done + + done = .false. + + !$omp parallel + !$omp master + num_threads = omp_get_num_threads() + !$omp end master + !$omp end parallel + + call init_with_boundaries(prev) + call init_with_boundaries(next) + + done = .false. + !$omp parallel + do while (.not. done) + !$omp do schedule(static) private(i) + do j = 2, SIZE-1 + do i = 2, SIZE-1 + next(i,j) = & + (prev(i-1, j) + & + prev(i+1, j) + & + prev(i, j-1) + & + prev(i, j+1)) / 4.0 + end do + end do + !$omp end do + delta = 0.0 + !$omp do schedule(static) private(i) reduction(max:delta) + do j = 2, SIZE-1 + do i = 2, SIZE-1 + prev(i,j) = & + (next(i-1, j) + & + next(i+1, j) + & + next(i, j-1) + & + next(i, j+1)) / 4.0 + delta = max(delta, abs(prev(i,j)-next(i,j))) + end do + end do + !$omp end do + !$omp single + if (delta < EPSILON) then + done = .true. + end if + !$omp end single + end do + !$omp end parallel + surface = prev +end subroutine + +subroutine init_with_boundaries(surface) + real, dimension(SIZE, SIZE), intent(out) :: surface + + surface = 0.0 + surface(1, :) = BOUNDARY_VALUE + surface(SIZE, :) = BOUNDARY_VALUE + surface(:, 1) = BOUNDARY_VALUE + surface(:, SIZE) = BOUNDARY_VALUE +end subroutine + +end program |