Commit 899bd7bf authored by Andreas Marek's avatar Andreas Marek

Merge branch 'loh/autotuning' into master_pre_stage

parents b0c34c81 29bab835
......@@ -35,6 +35,7 @@ noinst_LTLIBRARIES += libelpa@SUFFIX@_private.la
libelpa@SUFFIX@_private_la_FCFLAGS = $(AM_FCFLAGS) $(FC_MODOUT)private_modules $(FC_MODINC)private_modules
libelpa@SUFFIX@_private_la_SOURCES = \
src/elpa_impl.F90 \
src/elpa_autotune_impl.F90 \
src/elpa_abstract_impl.F90 \
src/helpers/mod_precision.F90 \
src/helpers/mod_mpi.F90 \
......
......@@ -124,8 +124,6 @@ the user application):
"debug" can be one of { 0 | 1 }, will give more information case of an error if set to 1
"eigenvalues_only" can be one of { 0 | 1 }, if set to 1 solve will only compute the eigenvalues
6. do the desired task with the *ELPA* library, which could be
a) e%eigenvectors ! solve EV problem with solver as set by "set" method; computes eigenvalues AND eigenvectors
......
......@@ -7,6 +7,10 @@
struct elpa_struct;
typedef struct elpa_struct *elpa_t;
struct elpa_autotune_struct;
typedef struct elpa_autotune_struct *elpa_autotune_t;
#include <elpa/elpa_constants.h>
#include <elpa/elpa_generated.h>
#include <elpa/elpa_generic.h>
......
......@@ -104,3 +104,21 @@ enum ELPA_CONSTANTS {
ELPA_2STAGE_NUMBER_OF_REAL_KERNELS = (0 ELPA_FOR_ALL_2STAGE_REAL_KERNELS(ELPA_ENUM_SUM)),
};
#define ELPA_FOR_ALL_AUTOTUNE_LEVELS(X, ...) \
X(ELPA_AUTOTUNE_NOT_TUNABLE, 0) \
X(ELPA_AUTOTUNE_FAST, 1) \
X(ELPA_AUTOTUNE_MEDIUM, 2)
enum ELPA_AUTOTUNE_LEVELS {
ELPA_FOR_ALL_AUTOTUNE_LEVELS(ELPA_ENUM_ENTRY)
};
#define ELPA_FOR_ALL_AUTOTUNE_DOMAINS(X, ...) \
X(ELPA_AUTOTUNE_DOMAIN_REAL, 1) \
X(ELPA_AUTOTUNE_DOMAIN_COMPLEX, 2) \
X(ELPA_AUTOTUNE_DOMAIN_ANY, 3)
enum ELPA_AUTOTUNE_DOMAINS {
ELPA_FOR_ALL_AUTOTUNE_DOMAINS(ELPA_ENUM_ENTRY)
};
......@@ -2,6 +2,11 @@
from __future__ import print_function
from itertools import product
language_flag = {
"Fortran" : "Fortran",
"C" : "C",
}
domain_flag = {
"real" : "-DTEST_REAL",
"complex": "-DTEST_COMPLEX",
......@@ -45,7 +50,8 @@ layout_flag = {
"square" : ""
}
for m, g, q, t, p, d, s, l in product(
for lang, m, g, q, t, p, d, s, l in product(
sorted(language_flag.keys()),
sorted(matrix_flag.keys()),
sorted(gpu_flag.keys()),
sorted(qr_flag.keys()),
......@@ -55,6 +61,11 @@ for m, g, q, t, p, d, s, l in product(
sorted(solver_flag.keys()),
sorted(layout_flag.keys())):
if (lang == "C"):
continue
if (lang == "C" and ( m == "analytic" or l == "all_layouts")):
continue
# exclude some test combinations
# analytic tests only for "eigenvectors" and not on GPU
......@@ -126,30 +137,86 @@ for m, g, q, t, p, d, s, l in product(
raise Exception("Oh no!")
endifs += 1
name = "test_{0}_{1}_{2}_{3}{4}_{5}{6}{7}{8}".format(
d, p, t, s,
"" if kernel == "nokernel" else "_" + kernel,
"gpu_" if g else "",
"qr_" if q else "",
m,
"_all_layouts" if l == "all_layouts" else "")
print("if BUILD_KCOMPUTER")
print("bin_PROGRAMS += " + name)
print("else")
print("noinst_PROGRAMS += " + name)
print("endif")
print("check_SCRIPTS += " + name + ".sh")
print(name + "_SOURCES = test/Fortran/test.F90")
print(name + "_LDADD = $(test_program_ldadd)")
print(name + "_FCFLAGS = $(test_program_fcflags) \\")
print(" -DTEST_CASE=\\\"{0}\\\" \\".format(name))
print(" " + " \\\n ".join([
if (lang == "Fortran"):
name = "test_{0}_{1}_{2}_{3}{4}_{5}{6}{7}{8}".format(
d, p, t, s,
"" if kernel == "nokernel" else "_" + kernel,
"gpu_" if g else "",
"qr_" if q else "",
m,
"_all_layouts" if l == "all_layouts" else "")
print("if BUILD_KCOMPUTER")
print("bin_PROGRAMS += " + name)
print("else")
print("noinst_PROGRAMS += " + name)
print("endif")
print("check_SCRIPTS += " + name + ".sh")
print(name + "_SOURCES = test/Fortran/test.F90")
print(name + "_LDADD = $(test_program_ldadd)")
print(name + "_FCFLAGS = $(test_program_fcflags) \\")
print(" -DTEST_CASE=\\\"{0}\\\" \\".format(name))
print(" " + " \\\n ".join([
domain_flag[d],
prec_flag[p],
test_type_flag[t],
solver_flag[s],
gpu_flag[g],
qr_flag[q],
matrix_flag[m]] + extra_flags))
print("endif\n" * endifs)
if (lang == "C"):
name = "test_c_version_{0}_{1}_{2}_{3}{4}_{5}{6}{7}{8}".format(
d, p, t, s,
"" if kernel == "nokernel" else "_" + kernel,
"gpu_" if g else "",
"qr_" if q else "",
m,
"_all_layouts" if l == "all_layouts" else "")
print("if BUILD_KCOMPUTER")
print("bin_PROGRAMS += " + name)
print("else")
print("noinst_PROGRAMS += " + name)
print("endif")
print("check_SCRIPTS += " + name + ".sh")
print(name + "_SOURCES = test/C/test.c")
print(name + "_LDADD = $(test_program_ldadd) $(FCLIBS)")
print(name + "_CFLAGS = $(test_program_fcflags) \\")
print(" -DTEST_CASE=\\\"{0}\\\" \\".format(name))
print(" " + " \\\n ".join([
domain_flag[d],
prec_flag[p],
test_type_flag[t],
solver_flag[s],
gpu_flag[g],
qr_flag[q],
matrix_flag[m]] + extra_flags))
print("endif\n" * endifs)
for p, d in product(sorted(prec_flag.keys()), sorted(domain_flag.keys())):
endifs = 0
if (p == "single"):
if (d == "real"):
print("if WANT_SINGLE_PRECISION_REAL")
elif (d == "complex"):
print("if WANT_SINGLE_PRECISION_COMPLEX")
else:
raise Exception("Oh no!")
endifs += 1
name = "test_autotune_{0}_{1}".format(d, p)
print("noinst_PROGRAMS += " + name)
#if (p != "single"):
# print("check_SCRIPTS += " + name + ".sh")
print(name + "_SOURCES = test/Fortran/test_autotune.F90")
print(name + "_LDADD = $(test_program_ldadd)")
print(name + "_FCFLAGS = $(test_program_fcflags) \\")
print(" " + " \\\n ".join([
domain_flag[d],
prec_flag[p],
test_type_flag[t],
solver_flag[s],
gpu_flag[g],
qr_flag[q],
matrix_flag[m]] + extra_flags))
print("endif\n" * endifs)
prec_flag[p]]))
print("endif\n" * endifs)
noinst_PROGRAMS += \
real_2stage_c_version@SUFFIX@ \
autotune_c_version@SUFFIX@ \
legacy_real_1stage@SUFFIX@ \
legacy_complex_1stage@SUFFIX@ \
legacy_real_2stage@SUFFIX@ \
......@@ -72,6 +74,14 @@ noinst_PROGRAMS += \
endif
endif
real_2stage_c_version@SUFFIX@_SOURCES = test/C/real_2stage_c_version.c
real_2stage_c_version@SUFFIX@_LDADD = $(test_program_ldadd) $(FCLIBS)
real_2stage_c_version@SUFFIX@_FCFLAGS = $(test_program_fcflags)
autotune_c_version@SUFFIX@_SOURCES = test/C/autotune_c_version.c
autotune_c_version@SUFFIX@_LDADD = $(test_program_ldadd) $(FCLIBS)
autotune_c_version@SUFFIX@_FCFLAGS = $(test_program_fcflags)
legacy_real_1stage_c_version@SUFFIX@_SOURCES = test/C/elpa1/legacy_interface/legacy_real_1stage_c_version.c
legacy_real_1stage_c_version@SUFFIX@_LDADD = $(test_program_ldadd) $(FCLIBS)
legacy_real_1stage_c_version@SUFFIX@_FCFLAGS = $(test_program_fcflags)
......
......@@ -208,14 +208,26 @@ module elpa
obj => elpa_impl_allocate()
end function
!> \brief function to deallocate an ELPA instance
!> Parameters
!> \details
!> \param obj class(elpa_t), pointer : pointer to object to be destroyed and deallocated
!> \param obj class(elpa_t), pointer : pointer to the ELPA object to be destroyed and deallocated
subroutine elpa_deallocate(obj)
class(elpa_t), pointer :: obj
call obj%destroy()
deallocate(obj)
end subroutine
!> \brief function to deallocate an ELPA autotune instance
!> Parameters
!> \details
!> \param obj class(elpa_autotune_t), pointer : pointer to the autotune object to be destroyed and deallocated
subroutine elpa_autotune_deallocate(obj)
class(elpa_autotune_t), pointer :: obj
call obj%destroy()
deallocate(obj)
end subroutine
end module
......@@ -72,28 +72,13 @@ module elpa_abstract_impl
type, abstract, extends(elpa_t) :: elpa_abstract_impl_t
#ifdef HAVE_DETAILED_TIMINGS
type(timer_t) :: timer
type(timer_t) :: autotune_timer
#else
type(timer_dummy_t) :: timer
#endif
type(c_ptr) :: index = C_NULL_PTR
logical :: eigenvalues_only
contains
! set private fields in the index
generic, public :: set_private => &
elpa_set_private_integer, &
elpa_set_private_double
generic, public :: get_private => &
elpa_get_private_integer, &
elpa_get_private_double
procedure, private :: elpa_set_private_integer
procedure, private :: elpa_set_private_double
procedure, private :: elpa_get_private_integer
procedure, private :: elpa_get_private_double
procedure, public :: elpa_set_integer !< private methods to implement the setting of an integer/double key/value pair
procedure, public :: elpa_set_double
......@@ -110,7 +95,7 @@ module elpa_abstract_impl
!> \param name string, the key
!> \param value integer, the value to be set
!> \result error integer, the error code
subroutine elpa_set_private_integer(self, name, value, error)
subroutine elpa_set_integer(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
......@@ -122,7 +107,7 @@ module elpa_abstract_impl
#endif
integer :: actual_error
actual_error = elpa_index_set_int_value_c(self%index, name // c_null_char, value, 0)
actual_error = elpa_index_set_int_value_c(self%index, name // c_null_char, value)
#ifdef USE_FORTRAN2008
if (present(error)) then
......@@ -143,7 +128,7 @@ module elpa_abstract_impl
!> \param name string, the key
!> \param value integer, the value of the key/vaue pair
!> \param error integer, optional, to store an error code
subroutine elpa_get_private_integer(self, name, value, error)
subroutine elpa_get_integer(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
......@@ -175,18 +160,19 @@ module elpa_abstract_impl
!> \param name string, the key
!> \param value double, the value to be set
!> \result error integer, the error code
subroutine elpa_set_private_double(self, name, value, error)
subroutine elpa_set_double(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
real(kind=c_double), intent(in) :: value
integer :: actual_error
#ifdef USE_FORTRAN2008
integer, optional :: error
#else
integer :: error
#endif
actual_error = elpa_index_set_double_value_c(self%index, name // c_null_char, value, 0)
actual_error = elpa_index_set_double_value_c(self%index, name // c_null_char, value)
#ifdef USE_FORTRAN2008
if (present(error)) then
......@@ -206,7 +192,7 @@ module elpa_abstract_impl
!> \param name string, the key
!> \param value double, the value of the key/vaue pair
!> \param error integer, optional, to store an error code
subroutine elpa_get_private_double(self, name, value, error)
subroutine elpa_get_double(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
......@@ -231,160 +217,4 @@ module elpa_abstract_impl
#endif
end subroutine
subroutine elpa_set_integer(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
integer(kind=c_int), intent(in) :: value
#ifdef USE_FORTRAN2008
integer, optional :: error
#else
integer :: error
#endif
integer :: actual_error
integer :: is_private
is_private = elpa_index_int_is_private_c(name // C_NULL_CHAR)
if (is_private == 0) then
call self%set_private(name, value, error)
else
if (is_private == 1) then
actual_error = ELPA_ERROR_ENTRY_NOT_FOUND
else
actual_error = is_private
endif
#ifdef USE_FORTRAN2008
if (present(error)) then
error = actual_error
else
write(error_unit,'(a)') "ELPA: Error setting option '" // name // "'" // &
" (got: " // elpa_strerr(actual_error) // ") and you did not check for errors!"
endif
#else
error = actual_error
#endif
endif
end subroutine
subroutine elpa_set_double(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
real(kind=c_double), intent(in) :: value
#ifdef USE_FORTRAN2008
integer, optional :: error
#else
integer :: error
#endif
integer :: actual_error
integer :: is_private
is_private = elpa_index_double_is_private_c(name // C_NULL_CHAR)
if (is_private == 0) then
call self%set_private(name, value, error)
else
if (is_private == 1) then
actual_error = ELPA_ERROR_ENTRY_NOT_FOUND
else
actual_error = is_private
endif
#ifdef USE_FORTRAN2008
if (present(error)) then
error = actual_error
else
write(error_unit,'(a)') "ELPA: Error setting option '" // name // "'" // &
" (got: " // elpa_strerr(actual_error) // ") and you did not check for errors!"
endif
#else
error = actual_error
#endif
endif
end subroutine
subroutine elpa_get_integer(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
integer(kind=c_int) :: value
#ifdef USE_FORTRAN2008
integer, optional, intent(out) :: error
#else
integer, intent(out) :: error
#endif
integer :: actual_error
integer :: is_private
is_private = elpa_index_int_is_private_c(name // C_NULL_CHAR)
if (is_private == 0) then
call self%get_private(name, value, error)
else
if (is_private == 1) then
actual_error = ELPA_ERROR_ENTRY_NOT_FOUND
else
actual_error = is_private
endif
#ifdef USE_FORTRAN2008
if (present(error)) then
error = actual_error
else
write(error_unit,'(a)') "ELPA: Error getting option '" // name // "'" // &
" (got: " // elpa_strerr(actual_error) // ") and you did not check for errors!"
endif
#else
error = actual_error
#endif
endif
end subroutine
subroutine elpa_get_double(self, name, value, error)
use iso_c_binding
class(elpa_abstract_impl_t) :: self
character(*), intent(in) :: name
real(kind=c_double) :: value
#ifdef USE_FORTRAN2008
integer, intent(out), optional :: error
#else
integer, intent(out) :: error
#endif
integer :: actual_error
integer :: is_private
is_private = elpa_index_double_is_private_c(name // C_NULL_CHAR)
if (is_private == 0) then
call self%get_private(name, value, error)
else
if (is_private == 1) then
actual_error = ELPA_ERROR_ENTRY_NOT_FOUND
else
actual_error = is_private
endif
#ifdef USE_FORTRAN2008
if (present(error)) then
error = actual_error
else
write(error_unit,'(a)') "ELPA: Error getting option '" // name // "'" // &
" (got: " // elpa_strerr(actual_error) // ") and you did not check for errors!"
endif
#else
error = actual_error
#endif
endif
end subroutine
end module
This diff is collapsed.
#include "config-f90.h"
module elpa_autotune_impl
use elpa_abstract_impl
use, intrinsic :: iso_c_binding
implicit none
type, extends(elpa_autotune_t) :: elpa_autotune_impl_t
class(elpa_abstract_impl_t), pointer :: parent => NULL()
integer :: i = 0
real(kind=C_DOUBLE) :: min_val = 0.0_C_DOUBLE
integer :: min_loc = 0
integer :: N = 0
integer :: level = 0
integer :: domain = 0
contains
procedure, public :: print => elpa_autotune_print
procedure, public :: destroy => elpa_autotune_destroy
end type
contains
!> \brief function to print the autotuning
!> Parameters
!> \param self class(elpa_autotune_impl_t) the allocated ELPA autotune object
subroutine elpa_autotune_print(self)
implicit none
class(elpa_autotune_impl_t), intent(in) :: self
!print *, "Print me"
end subroutine
!> \brief function to destroy an elpa autotune object
!> Parameters
!> \param self class(elpa_autotune_impl_t) the allocated ELPA autotune object
subroutine elpa_autotune_destroy(self)
implicit none
class(elpa_autotune_impl_t), intent(inout) :: self
! nothing to do atm
end subroutine
end module
This diff is collapsed.
This diff is collapsed.
......@@ -90,13 +90,14 @@ typedef struct {
char *env_force;
int once;
int readonly;
int private;
} elpa_index_entry_t;
typedef struct {
elpa_index_entry_t base;
int default_value;
int autotune_level;
int autotune_domain;
elpa_index_valid_int_t valid;
elpa_index_cardinality_t cardinality;
elpa_index_enumerate_int_option_t enumerate;
......@@ -169,18 +170,17 @@ int elpa_index_get_int_value(elpa_index_t index, char *name, int *success);
/*
!f> interface
!f> function elpa_index_set_int_value_c(index, name, value, force_writable) result(success) &
!f> function elpa_index_set_int_value_c(index, name, value) result(success) &
!f> bind(C, name="elpa_index_set_int_value")
!f> import c_ptr, c_int, c_char
!f> type(c_ptr), value :: index
!f> character(kind=c_char), intent(in) :: name(*)
!f> integer(kind=c_int),intent(in), value :: value
!f> integer(kind=c_int),intent(in), value :: force_writable
!f> integer(kind=c_int) :: success
!f> end function
!f> end interface
*/
int elpa_index_set_int_value(elpa_index_t index, char *name, int value, int force_writable);
int elpa_index_set_int_value(elpa_index_t index, char *name, int value);
/*
......@@ -196,30 +196,6 @@ int elpa_index_set_int_value(elpa_index_t index, char *name, int value, int forc
int elpa_index_int_value_is_set(elpa_index_t index, char *name);
/*
!f> interface
!f> function elpa_index_int_is_private_c(name) result(success) bind(C, name="elpa_index_int_is_private")
!f> import c_int, c_char
!f> character(kind=c_char), intent(in) :: name(*)
!f> integer(kind=c_int) :: success
!f> end function
!f> end interface
*/
int elpa_index_int_is_private(char *name);
/*
!f> interface
!f> function elpa_index_double_is_private_c(name) result(success) bind(C, name="elpa_index_double_is_private")
!f> import c_int, c_char
!f> character(kind=c_char), intent(in) :: name(*)
!f> integer(kind=c_int) :: success
!f> end function
!f> end interface
*/
int elpa_index_double_is_private(char *name);
/*
!f> interface
!f> function elpa_index_get_int_loc_c(index, name) result(loc) bind(C, name="elpa_index_get_int_loc")
......@@ -253,18 +229,17 @@ double elpa_index_get_double_value(elpa_index_t index, char *name, int *success)
/*
!f> interface
!f> function elpa_index_set_double_value_c(index, name, value, force_writable) result(success) &
!f> function elpa_index_set_double_value_c(index, name, value) result(success) &
!f> bind(C, name="elpa_index_set_double_value")
!f> import c_ptr, c_int, c_double, c_char
!f> type(c_ptr), value :: index
!f> character(kind=c_char), intent(in) :: name(*)
!f> real(kind=c_double),intent(in), value :: value
!f> integer(kind=c_int),intent(in), value :: force_writable
!f> integer(kind=c_int) :: success
!f> end function
!f> end interface
*/
int elpa_index_set_double_value(elpa_index_t index, char *name, double value, int force_writable);
int elpa_index_set_double_value(elpa_index_t index, char *name, double value);
/*
......@@ -396,7 +371,8 @@ int elpa_option_enumerate(char *name, int i);
/*
!f> interface
!f> function elpa_index_int_is_valid_c(index, name, new_value) result(success) bind(C, name="elpa_index_int_is_valid")
!f> function elpa_index_int_is_valid_c(index, name, new_value) result(success) &
!f> bind(C, name="elpa_index_int_is_valid")
!f> import c_int, c_ptr, c_char
!f> type(c_ptr), intent(in), value :: index
!f> character(kind=c_char), intent(in) :: name(*)
......@@ -407,3 +383,33 @@ int elpa_option_enumerate(char *name, int i);
!f>