From 235b7094af27bdb460fd034d4bcfb474e7a0075f Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Mon, 4 Mar 2013 11:24:50 +0000 Subject: [PATCH] refactoring of the lower level of the DBCSR multiply (Ole Schuett). svn-origin-rev: 12737 --- cuda_tools/dbcsr_cuda_calc.cu | 38 +- cuda_tools/dbcsr_cuda_calc_c.cu | 4 +- cuda_tools/dbcsr_cuda_calc_d.cu | 20 +- cuda_tools/dbcsr_cuda_calc_r.cu | 4 +- cuda_tools/dbcsr_cuda_calc_z.cu | 4 +- cuda_tools/dbcsr_cuda_dev.cu | 3 + cuda_tools/dbcsr_cuda_mem.cu | 12 + src/cp_dbcsr_interface.F | 28 +- src/dbcsr_lib/OBJECTDEFS | 2 - src/dbcsr_lib/dbcsr_config.F | 22 +- src/dbcsr_lib/dbcsr_cuda_device.F | 38 +- src/dbcsr_lib/dbcsr_cuda_memory.F | 141 +- .../dbcsr_cuda_memory__nametype1_.template | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_c.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_d.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_i.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_l.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_r.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_memory_z.F | 200 +-- src/dbcsr_lib/dbcsr_cuda_types.F | 10 +- src/dbcsr_lib/dbcsr_data_methods.F | 24 +- src/dbcsr_lib/dbcsr_mm_cannon.F | 93 +- src/dbcsr_lib/dbcsr_mm_csr.F | 1328 ++++++++--------- src/dbcsr_lib/dbcsr_mm_driver.F | 830 +++++++---- src/dbcsr_lib/dbcsr_mm_multrec.F | 453 +++--- src/dbcsr_lib/dbcsr_mm_stack.F | 706 +-------- src/dbcsr_lib/dbcsr_mm_types.F | 103 +- src/dbcsr_lib/dbcsr_operations.F | 119 +- src/dbcsr_lib/dbcsr_ptr_util.F | 4 +- .../dbcsr_ptr_util__nametype1_.template | 4 +- src/dbcsr_lib/dbcsr_ptr_util_c.F | 4 +- src/dbcsr_lib/dbcsr_ptr_util_d.F | 4 +- src/dbcsr_lib/dbcsr_ptr_util_s.F | 4 +- src/dbcsr_lib/dbcsr_ptr_util_z.F | 4 +- src/input_cp2k.F | 37 +- tests/LIBTEST/dbcsr_multistack.inp | 1 - 36 files changed, 2565 insertions(+), 2879 deletions(-) diff --git a/cuda_tools/dbcsr_cuda_calc.cu b/cuda_tools/dbcsr_cuda_calc.cu index 325c3d076c..b662f0fcd8 100644 --- a/cuda_tools/dbcsr_cuda_calc.cu +++ b/cuda_tools/dbcsr_cuda_calc.cu @@ -39,25 +39,25 @@ __global__ void stack_mm_r int stack_size, int nparams, const float *__restrict__ a_data, const float *__restrict__ b_data, - float *__restrict__ c_data, int *__restrict__ c_locks); + float *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset); __global__ void stack_mm_d (const int *__restrict__ param_stack, int stack_size, int nparams, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks); + double *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset); __global__ void stack_mm_c (const int *__restrict__ param_stack, int stack_size, int nparams, const float *__restrict__ a_data, const float *__restrict__ b_data, - float *__restrict__ c_data, int *__restrict__ c_locks); + float *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset); __global__ void stack_mm_z (const int *__restrict__ param_stack, int stack_size, int nparams, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks); + double *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset); __global__ void stack_mm_mnk_d (const int *__restrict__ param_stack, const int careful, const int nruns, @@ -66,7 +66,7 @@ __global__ void stack_mm_mnk_d (const int *__restrict__ param_stack, const double *__restrict__ a_data, const double *__restrict__ b_data, double *__restrict__ c_data, - int *__restrict__ c_locks); + int *__restrict__ c_locks, int lock_offset); __global__ void stack_mm_mnk_sq23_d (const int *__restrict__ param_stack, const int careful, const int nruns, @@ -75,7 +75,8 @@ __global__ void stack_mm_mnk_sq23_d (const int *__restrict__ param_stack, const double *__restrict__ a_data, const double *__restrict__ b_data, double *__restrict__ c_data, - int *__restrict__ c_locks); + int *__restrict__ c_locks, + int lock_offset); __global__ void stack_mm_mnk_sq5_d (const int *__restrict__ param_stack, const int careful, const int nruns, @@ -84,7 +85,8 @@ __global__ void stack_mm_mnk_sq5_d (const int *__restrict__ param_stack, const double *__restrict__ a_data, const double *__restrict__ b_data, double *__restrict__ c_data, - int *__restrict__ c_locks); + int *__restrict__ c_locks, + int lock_offset); /** * \brief Bridge routine to call appropriate CUDA kernel. @@ -129,7 +131,8 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, return 4; stack_mm_r <<< stack_size, maxt, shared_size, stream >>> (param_stack, stack_size, nparams, - (float *) a_data, (float *) b_data, (float *) c_data, c_locks); + (float *) a_data, (float *) b_data, (float *) c_data, c_locks, + pow (2, 15) * stream_id); break; case 3: /* Real, double precision */ @@ -164,7 +167,9 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, shared_size, stream >>> (param_stack, careful, nruns, m_max, n_max, k_max, liter, (double *) a_data, (double *) b_data, - (double *) c_data, c_locks); + (double *) c_data, c_locks, pow (2, + 15) + * stream_id); } else if (m_max == 5 && n_max == 5 && k_max == 5) { @@ -177,7 +182,8 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, m_max, n_max, k_max, liter, (double *) a_data, (double *) b_data, - (double *) c_data, c_locks); + (double *) c_data, c_locks, + pow (2, 15) * stream_id); } else { @@ -187,7 +193,9 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, //mn, mk, nk, maxb, liter, liter, (double *) a_data, (double *) b_data, - (double *) c_data, c_locks); + (double *) c_data, c_locks, pow (2, + 15) + * stream_id); } } else @@ -200,7 +208,7 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, stack_mm_d <<< stack_size, maxt, shared_size, stream >>> (param_stack, stack_size, nparams, (double *) a_data, (double *) b_data, (double *) c_data, - c_locks); + c_locks, pow (2, 15) * stream_id); } break; case 5: @@ -210,7 +218,8 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, return 4; stack_mm_c <<< stack_size, maxt, shared_size, stream >>> (param_stack, stack_size, nparams, - (float *) a_data, (float *) b_data, (float *) c_data, c_locks); + (float *) a_data, (float *) b_data, (float *) c_data, c_locks, + pow (2, 15) * stream_id); break; case 7: /* Complex, double precision */ @@ -219,7 +228,8 @@ dc_do_stack_cu (int *param_stack, int stack_size, int nparams, return 4; stack_mm_z <<< stack_size, maxt, shared_size, stream >>> (param_stack, stack_size, nparams, - (double *) a_data, (double *) b_data, (double *) c_data, c_locks); + (double *) a_data, (double *) b_data, (double *) c_data, c_locks, + pow (2, 15) * stream_id); break; default: return 2; diff --git a/cuda_tools/dbcsr_cuda_calc_c.cu b/cuda_tools/dbcsr_cuda_calc_c.cu index 9a8925d31e..ebcd13541d 100644 --- a/cuda_tools/dbcsr_cuda_calc_c.cu +++ b/cuda_tools/dbcsr_cuda_calc_c.cu @@ -12,7 +12,7 @@ __global__ void stack_mm_c int stack_size, int nparams, const float *__restrict__ a_data, const float *__restrict__ b_data, - float *__restrict__ c_data, int *__restrict__ c_locks) + float *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset) { /** @@ -117,7 +117,7 @@ __global__ void stack_mm_c // /* Lock the C block. */ // syncthreads(); // if (tn == 0) { - // sp_one = sp + 1; + // sp_one = lock_offset + sp + 1; // c_id = our_params[6]-1; // lock_owner = 0; // while ((lock_owner != sp_one)) diff --git a/cuda_tools/dbcsr_cuda_calc_d.cu b/cuda_tools/dbcsr_cuda_calc_d.cu index 8e8c946e41..0a0e4c657a 100644 --- a/cuda_tools/dbcsr_cuda_calc_d.cu +++ b/cuda_tools/dbcsr_cuda_calc_d.cu @@ -50,7 +50,8 @@ stack_mm_mnk_sq23_d (const int *__restrict__ param_stack, const int liter, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks) + double *__restrict__ c_data, int *__restrict__ c_locks, + int lock_offset) { /** @@ -227,7 +228,7 @@ stack_mm_mnk_sq23_d (const int *__restrict__ param_stack, c_loc = param_stack[psp + 5] - 1; // c_id = param_stack[psp+6]-1; // if (threadIdx.x == 0) { - // my_id = blockIdx.x+1; + // my_id = lock_offset + blockIdx.x+1; // lock_owner = 0; // while ((lock_owner != my_id)) // lock_owner = atomicCAS (&(c_locks[c_id]), 0, my_id); @@ -347,7 +348,8 @@ stack_mm_mnk_sq5_d (const int *__restrict__ param_stack, const int liter, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks) + double *__restrict__ c_data, int *__restrict__ c_locks, + int lock_offset) { /** @@ -519,7 +521,8 @@ stack_mm_mnk_sq5_d (const int *__restrict__ param_stack, /* if (lid == 0) { - my_id = 4*blockIdx.x + wid + 1; + // TODO: make shure 2^16 is enough as lock_offset stepsize + my_id = lock_offset + 4*blockIdx.x + wid + 1; int lock_owner = 0; while ((lock_owner != my_id)) lock_owner = atomicCAS (&(c_locks[c_id]), 0, my_id); @@ -556,7 +559,8 @@ stack_mm_mnk_d (const int *__restrict__ param_stack, const int liter, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks) + double *__restrict__ c_data, int *__restrict__ c_locks, + int lock_offset) { /** @@ -646,7 +650,7 @@ stack_mm_mnk_d (const int *__restrict__ param_stack, // c_id = param_stack[psp+6]-1; // // if (threadIdx.x == 0) { - // my_id = blockIdx.x+1; + // my_id = lock_offset + blockIdx.x+1; // lock_owner = 0; // while ((lock_owner != my_id)) // lock_owner = atomicCAS (&(c_locks[c_id]), 0, my_id); @@ -682,7 +686,7 @@ __global__ void stack_mm_d int stack_size, int nparams, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks) + double *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset) { /** @@ -754,7 +758,7 @@ __global__ void stack_mm_d // c_loc = param_stack[psp+5]-1; // syncthreads(); // if (tn == 0) { - // sp_one = sp + 1; + // sp_one = lock_offset + sp + 1; // lock_owner = 0; // while ((lock_owner != sp_one)) // lock_owner = atomicCAS (&(c_locks[c_id]), 0, sp_one); diff --git a/cuda_tools/dbcsr_cuda_calc_r.cu b/cuda_tools/dbcsr_cuda_calc_r.cu index f6c23c7c8f..8a5ddd9395 100644 --- a/cuda_tools/dbcsr_cuda_calc_r.cu +++ b/cuda_tools/dbcsr_cuda_calc_r.cu @@ -12,7 +12,7 @@ __global__ void stack_mm_r int stack_size, int nparams, const float *__restrict__ a_data, const float *__restrict__ b_data, - float *__restrict__ c_data, int *__restrict__ c_locks) + float *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset) { /** @@ -104,7 +104,7 @@ __global__ void stack_mm_r // /* Lock the C block. */ // syncthreads(); // if (tn == 0) { - // sp_one = sp + 1; + // sp_one = lock_offset + sp + 1; // c_id = our_params[6]-1; // lock_owner = 0; // while ((lock_owner != sp_one)) diff --git a/cuda_tools/dbcsr_cuda_calc_z.cu b/cuda_tools/dbcsr_cuda_calc_z.cu index 534046a680..3cdecbef76 100644 --- a/cuda_tools/dbcsr_cuda_calc_z.cu +++ b/cuda_tools/dbcsr_cuda_calc_z.cu @@ -12,7 +12,7 @@ __global__ void stack_mm_z int stack_size, int nparams, const double *__restrict__ a_data, const double *__restrict__ b_data, - double *__restrict__ c_data, int *__restrict__ c_locks) + double *__restrict__ c_data, int *__restrict__ c_locks, int lock_offset) { /** @@ -121,7 +121,7 @@ __global__ void stack_mm_z // /* Lock the C block. */ // syncthreads(); // if (tn == 0) { - // sp_one = sp + 1; + // sp_one = lock_offset + sp + 1; // c_id = our_params[6]-1; // lock_owner = 0; // while ((lock_owner != sp_one)) diff --git a/cuda_tools/dbcsr_cuda_dev.cu b/cuda_tools/dbcsr_cuda_dev.cu index 58af3b9bd5..08c7384893 100644 --- a/cuda_tools/dbcsr_cuda_dev.cu +++ b/cuda_tools/dbcsr_cuda_dev.cu @@ -56,6 +56,9 @@ dc_set_device_cu (int device_id) if (cuda_error_check (cErr)) return 1; + if (myDevice != device_id) + return 1; + cErr = cudaGetDeviceProperties (&devProperties, myDevice); if (cuda_error_check (cErr)) return 1; diff --git a/cuda_tools/dbcsr_cuda_mem.cu b/cuda_tools/dbcsr_cuda_mem.cu index 942722defa..e312d0192a 100644 --- a/cuda_tools/dbcsr_cuda_mem.cu +++ b/cuda_tools/dbcsr_cuda_mem.cu @@ -280,3 +280,15 @@ dc_memzero_cu (void *dev_mem, size_t offset, size_t length) if (cuda_error_check (cudaGetLastError())) return 1; */ return 0; } + +extern "C" int +dc_dev_mem_info_cu (size_t * free, size_t * avail) +{ + cudaError_t cErr; + cErr = cudaMemGetInfo (free, avail); + if (cuda_error_check (cErr)) + return 1; + if (cuda_error_check (cudaGetLastError ())) + return 1; + return 0; +} diff --git a/src/cp_dbcsr_interface.F b/src/cp_dbcsr_interface.F index 57f1cd06fa..112215b6d9 100644 --- a/src/cp_dbcsr_interface.F +++ b/src/cp_dbcsr_interface.F @@ -46,8 +46,7 @@ MODULE cp_dbcsr_interface dbcsr_set_conf_nstacks, dbcsr_set_conf_subcomm, & dbcsr_set_conf_use_comm_thread, has_cuda, has_mpi, mm_driver_blas, & mm_driver_cuda, mm_driver_matmul, mm_driver_plasma, mm_driver_smm, & - mm_name_blas, mm_name_cuda, mm_name_matmul, mm_name_plasma, & - mm_name_smm, mm_thread_workshare + mm_name_blas, mm_name_cuda, mm_name_matmul, mm_name_plasma, mm_name_smm USE dbcsr_data_methods, ONLY: dbcsr_scalar,& dbcsr_scalar_fill_all,& dbcsr_scalar_get_value,& @@ -433,8 +432,7 @@ CONTAINS INTEGER :: comm_thread_load, & error_handle, mm_driver, & - mm_ss, n_mem_regions, & - n_stack_buffers + mm_ss, n_stack_buffers INTEGER, DIMENSION(3) :: nstacks LOGICAL :: use_combtypes, & use_comm_thread, & @@ -463,15 +461,11 @@ CONTAINS "mm_stack_size", i_val=mm_ss, error=error) CALL section_vals_val_get(dbcsr_section,& "mm_driver", i_val=mm_driver, error=error) - CALL section_vals_val_get(dbcsr_section,& - "mm_thread_workshare", l_val=mm_thread_workshare, error=error) CALL section_vals_val_get(dbcsr_section,& "n_size_mnk_stacks", i_val=nstacks(1), error=error) nstacks(2:3) = nstacks(1) CALL section_vals_val_get(dbcsr_section,& "n_stack_buffers", i_val=n_stack_buffers, error=error) - CALL section_vals_val_get(dbcsr_section,& - "n_stack_memory_regions", i_val=n_mem_regions, error=error) CALL section_vals_val_get(dbcsr_section,& "use_comm_thread", l_val=use_comm_thread, error=error) CALL section_vals_val_get(dbcsr_section,& @@ -482,8 +476,7 @@ CONTAINS CALL dbcsr_set_conf_mpi_mem (use_mpi_mem, error=dbcsr_error) CALL dbcsr_set_conf_cuda_mem (use_cuda_mem, error=dbcsr_error) CALL dbcsr_set_conf_mm_stacksize (mm_ss, error=dbcsr_error) - CALL dbcsr_set_conf_nstacks(nstacks, n_stack_buffers, n_mem_regions,& - error=dbcsr_error) + CALL dbcsr_set_conf_nstacks(nstacks, n_stack_buffers, error=dbcsr_error) CALL dbcsr_set_conf_use_comm_thread(use_comm_thread, error=dbcsr_error) CALL dbcsr_set_conf_comm_thread_load(comm_thread_load, error=dbcsr_error) CALL dbcsr_error_stop (error_handle, dbcsr_error) @@ -504,11 +497,10 @@ CONTAINS CHARACTER(len=default_string_length) :: comm_thread_load_str, mm_name, & mm_ss_str, use_combtypes_str, use_comm_thread_str, use_cuda_mem_str, & - use_k_stacks, use_m_stacks, use_mem_regions, use_mpi_mem_str, & - use_n_stacks, use_stack_buffers, use_subcomms_str + use_k_stacks, use_m_stacks, use_mpi_mem_str, use_n_stacks, & + use_stack_buffers, use_subcomms_str INTEGER :: comm_thread_load, mm_driver, & - mm_ss, nbuffers, nmemregions, & - unit_num + mm_ss, nbuffers, unit_num INTEGER, DIMENSION(3) :: n_mnk_stacks LOGICAL :: use_combtypes, & use_comm_thread, & @@ -544,10 +536,8 @@ CONTAINS use_comm_thread_str = l2str_r(use_comm_thread,info_len) comm_thread_load_str = int2str_r(comm_thread_load,info_len) - CALL dbcsr_get_conf_nstacks (n_mnk_stacks, nbuffers, nmemregions,& - error=dbcsr_error) + CALL dbcsr_get_conf_nstacks (n_mnk_stacks, nbuffers, error=dbcsr_error) use_stack_buffers = int2str_r (nbuffers, info_len) - use_mem_regions = int2str_r (nmemregions, info_len) use_m_stacks = int2str_r (n_mnk_stacks(1), info_len) use_n_stacks = int2str_r (n_mnk_stacks(2), info_len) use_k_stacks = int2str_r (n_mnk_stacks(3), info_len) @@ -562,10 +552,6 @@ CONTAINS WRITE(UNIT=unit_num, FMT=o_fmt) & plabel, "Multiplication driver", mm_name(1:info_len),& plabel, "Multiplication stack size", mm_ss_str(1:info_len) - IF (nmemregions .NE. 1) & - WRITE(UNIT=unit_num, FMT=o_fmt) & - plabel, "Multiplication stack memory regions",& - use_mem_regions(1:info_len) IF (nbuffers .NE. 1) & WRITE(UNIT=unit_num, FMT=o_fmt) & plabel, "Multiplication stack buffers",& diff --git a/src/dbcsr_lib/OBJECTDEFS b/src/dbcsr_lib/OBJECTDEFS index 20888f5ee2..748ae0365b 100644 --- a/src/dbcsr_lib/OBJECTDEFS +++ b/src/dbcsr_lib/OBJECTDEFS @@ -34,8 +34,6 @@ LIB3_OBJECTS =\ dbcsr_operations.o\ dbcsr_performance_multiply.o\ dbcsr_plasma_interface.o\ - dbcsr_pq_methods.o\ - dbcsr_pq_types.o\ dbcsr_ptr_util.o\ dbcsr_test_add.o\ dbcsr_test_methods.o\ diff --git a/src/dbcsr_lib/dbcsr_config.F b/src/dbcsr_lib/dbcsr_config.F index b8d9c4a766..4060f0d9ca 100644 --- a/src/dbcsr_lib/dbcsr_config.F +++ b/src/dbcsr_lib/dbcsr_config.F @@ -69,12 +69,11 @@ MODULE dbcsr_config mm_name_smm,& mm_name_plasma,& mm_name_cuda - PUBLIC :: nm_stacks, nn_stacks, nk_stacks, nstackbuffers, nstackmemregions + PUBLIC :: nm_stacks, nn_stacks, nk_stacks, nstackbuffers PUBLIC :: use_comm_thread, comm_thread_load ! PUBLIC :: is_configured - PUBLIC :: mm_thread_workshare ! First the constants are declared. @@ -156,16 +155,13 @@ MODULE dbcsr_config INTEGER, SAVE :: nn_stacks = 0 INTEGER, SAVE :: nk_stacks = 0 INTEGER, SAVE :: nstackbuffers = 1 - INTEGER, SAVE :: nstackmemregions = 1 - + ! Configuration of an MPI progress thread LOGICAL, SAVE :: use_comm_thread = .TRUE. INTEGER, SAVE :: comm_thread_load = 100 LOGICAL, SAVE :: is_configured = .FALSE. - ! Worksharing between threads - LOGICAL, SAVE :: mm_thread_workshare = .TRUE. CONTAINS @@ -201,16 +197,12 @@ CONTAINS ! use_comm_thread = .TRUE. comm_thread_load = 100 - mm_thread_workshare = .FALSE. - !$ mm_thread_workshare = .TRUE. mm_async = driver_is_async (mm_driver) IF (mm_async) THEN mm_host_driver = mm_driver_smm - mm_thread_workshare = .FALSE. ELSE mm_host_driver = mm_driver ENDIF - IF (has_cuda) mm_thread_workshare = .FALSE. CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dbcsr_init_conf @@ -390,8 +382,8 @@ CONTAINS END FUNCTION dbcsr_get_conf_mm_stacksize - SUBROUTINE dbcsr_set_conf_nstacks (nstacks, nbuffers, nmemregs, error) - INTEGER, INTENT(IN) :: nstacks(:), nbuffers, nmemregs + SUBROUTINE dbcsr_set_conf_nstacks (nstacks, nbuffers, error) + INTEGER, INTENT(IN) :: nstacks(:), nbuffers TYPE(dbcsr_error_type), INTENT(INOUT) :: error CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_set_conf_nstacks', & @@ -407,12 +399,11 @@ CONTAINS nn_stacks = nstacks(2) nk_stacks = nstacks(3) nstackbuffers = nbuffers - nstackmemregions = nmemregs CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dbcsr_set_conf_nstacks - SUBROUTINE dbcsr_get_conf_nstacks (nstacks, nbuffers, nmemregs, error) - INTEGER, INTENT(OUT) :: nstacks(:), nbuffers, nmemregs + SUBROUTINE dbcsr_get_conf_nstacks (nstacks, nbuffers, error) + INTEGER, INTENT(OUT) :: nstacks(:), nbuffers TYPE(dbcsr_error_type), INTENT(INOUT) :: error CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_get_conf_nstacks', & @@ -428,7 +419,6 @@ CONTAINS nstacks(2) = nn_stacks nstacks(3) = nk_stacks nbuffers = nstackbuffers - nmemregs = nstackmemregions CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dbcsr_get_conf_nstacks diff --git a/src/dbcsr_lib/dbcsr_cuda_device.F b/src/dbcsr_lib/dbcsr_cuda_device.F index 76f716e66d..b123d227b7 100644 --- a/src/dbcsr_lib/dbcsr_cuda_device.F +++ b/src/dbcsr_lib/dbcsr_cuda_device.F @@ -149,7 +149,7 @@ CONTAINS IF (PRESENT (card_num)) THEN icard = card_num ELSE - + icard = 0 ENDIF istat = cuda_set_device_cu (icard) #else @@ -212,14 +212,7 @@ CONTAINS #else istat = -1 #endif - IF (istat /= 0) THEN - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not synchronize all threads",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) STOP "dbcsr_cuda_device_sync: Could not synchronize all threads" CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_cuda_device_sync @@ -241,14 +234,7 @@ CONTAINS #else istat = -1 #endif - IF (istat /= 0) THEN - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not synchronize stream",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) STOP "dbcsr_cuda_stream_sync: Could not synchronize stream" CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_cuda_stream_sync @@ -271,14 +257,7 @@ CONTAINS #else istat = -1 #endif - IF (istat /= 0) THEN - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not create streams",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) STOP "dbcsr_cuda_create_streams: Could not create streams" CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_cuda_create_streams @@ -299,14 +278,7 @@ CONTAINS #else istat = -1 #endif - IF (istat /= 0) THEN - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not destroy streams",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) STOP "dbcsr_cuda_destroy_streams: Could not destroy streams" CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_cuda_destroy_streams diff --git a/src/dbcsr_lib/dbcsr_cuda_memory.F b/src/dbcsr_lib/dbcsr_cuda_memory.F index 61030a1635..0ca91e83fe 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory.F @@ -61,7 +61,7 @@ MODULE dbcsr_cuda_memory PUBLIC :: dbcsr_cuda_dev_mem_init PUBLIC :: dbcsr_cuda_dev_mem_new, dbcsr_cuda_dev_mem_release,& dbcsr_cuda_dev_mem_hold - + PUBLIC :: dbcsr_cuda_dev_mem_info INTERFACE dbcsr_cuda_dev_mem_alloc MODULE PROCEDURE dev_mem_alloc_any @@ -88,12 +88,24 @@ MODULE dbcsr_cuda_memory MODULE PROCEDURE host_mem_alloc_i, host_mem_alloc_l MODULE PROCEDURE host_mem_alloc_r, host_mem_alloc_d MODULE PROCEDURE host_mem_alloc_c, host_mem_alloc_z + MODULE PROCEDURE host_mem_alloc_i_2D, host_mem_alloc_l_2D + MODULE PROCEDURE host_mem_alloc_r_2D, host_mem_alloc_d_2D + MODULE PROCEDURE host_mem_alloc_c_2D, host_mem_alloc_z_2D + MODULE PROCEDURE host_mem_alloc_i_4D, host_mem_alloc_l_4D + MODULE PROCEDURE host_mem_alloc_r_4D, host_mem_alloc_d_4D + MODULE PROCEDURE host_mem_alloc_c_4D, host_mem_alloc_z_4D END INTERFACE INTERFACE dbcsr_cuda_host_mem_dealloc MODULE PROCEDURE host_mem_dealloc_i, host_mem_dealloc_l MODULE PROCEDURE host_mem_dealloc_r, host_mem_dealloc_d MODULE PROCEDURE host_mem_dealloc_c, host_mem_dealloc_z + MODULE PROCEDURE host_mem_dealloc_i_2D, host_mem_dealloc_l_2D + MODULE PROCEDURE host_mem_dealloc_r_2D, host_mem_dealloc_d_2D + MODULE PROCEDURE host_mem_dealloc_c_2D, host_mem_dealloc_z_2D + MODULE PROCEDURE host_mem_dealloc_i_4D, host_mem_dealloc_l_4D + MODULE PROCEDURE host_mem_dealloc_r_4D, host_mem_dealloc_d_4D + MODULE PROCEDURE host_mem_dealloc_c_4D, host_mem_dealloc_z_4D END INTERFACE INTERFACE dbcsr_cuda_dev_mem_zero @@ -106,6 +118,17 @@ MODULE dbcsr_cuda_memory #if defined (__DBCSR_CUDA) + + INTERFACE + FUNCTION dbcsr_cuda_dev_mem_info(free, avail) RESULT (istat) BIND(C, name="dc_dev_mem_info_cu") + USE ISO_C_BINDING + INTEGER(KIND=C_INT), INTENT(OUT) :: free, avail + INTEGER(KIND=C_INT) :: istat + + END FUNCTION dbcsr_cuda_dev_mem_info + END INTERFACE + + INTERFACE FUNCTION cuda_dev_mem_alloc_cu(mem, n) RESULT (istat) BIND(C, name="dc_dev_mem_alloc") USE ISO_C_BINDING @@ -177,6 +200,17 @@ MODULE dbcsr_cuda_memory CONTAINS +#if ! defined (__DBCSR_CUDA) + FUNCTION dbcsr_cuda_dev_mem_info(free, avail) RESULT (istat) + INTEGER, INTENT(OUT) :: free, avail + INTEGER :: istat + + free = 0 + avail = 0 + istat = -1 + END FUNCTION dbcsr_cuda_dev_mem_info +#endif + #include "dbcsr_cuda_memory_i.F" #include "dbcsr_cuda_memory_l.F" @@ -189,6 +223,35 @@ CONTAINS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! Encapsulated memory routines for the device +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_raw (host_mem_c_ptr, n_bytes, error) + TYPE(C_PTR), INTENT(OUT) :: host_mem_c_ptr + INTEGER, INTENT(IN) :: n_bytes + TYPE(dbcsr_error_type), INTENT(INOUT), & + OPTIONAL :: error + + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_raw', & + routineP = moduleN//':'//routineN + + INTEGER :: error_handle, istat + + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_alloc_cu(host_mem_c_ptr, & + INT(n_bytes, KIND=C_SIZE_T), 0_c_int, 0_c_int) + IF (istat /= 0) STOP "host_mem_alloc_raw: Could not allocate host pinned memory" +#else + STOP "host_mem_alloc_raw: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_alloc_raw + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dbcsr_cuda_dev_mem_init (dev_mem, error) TYPE(dbcsr_cuda_mem_type), POINTER :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT) :: error @@ -196,14 +259,16 @@ CONTAINS NULLIFY (dev_mem) END SUBROUTINE dbcsr_cuda_dev_mem_init + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dbcsr_cuda_dev_mem_new (dev_mem, data_type, error) TYPE(dbcsr_cuda_mem_type), POINTER :: dev_mem INTEGER, INTENT(IN), OPTIONAL :: data_type TYPE(dbcsr_error_type), INTENT(INOUT) :: error - INTEGER :: stat - - ALLOCATE (dev_mem, stat=stat) + ALLOCATE (dev_mem) dev_mem%data_type = 0 dev_mem%refcount = 1 IF (PRESENT (data_type)) THEN @@ -211,6 +276,10 @@ CONTAINS ENDIF END SUBROUTINE dbcsr_cuda_dev_mem_new + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dbcsr_cuda_dev_mem_hold (dev_mem, error) TYPE(dbcsr_cuda_mem_type), POINTER :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT) :: error @@ -219,21 +288,25 @@ CONTAINS END SUBROUTINE dbcsr_cuda_dev_mem_hold +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dbcsr_cuda_dev_mem_release (dev_mem, error) TYPE(dbcsr_cuda_mem_type), POINTER :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT) :: error - INTEGER :: stat - dev_mem%refcount = dev_mem%refcount - 1 IF (dev_mem%refcount == 0) THEN CALL dev_mem_dealloc_any (dev_mem, error=error) - DEALLOCATE (dev_mem, stat=stat) + DEALLOCATE (dev_mem) NULLIFY (dev_mem) ENDIF END SUBROUTINE dbcsr_cuda_dev_mem_release +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_any (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type), INTENT(INOUT) :: dev_mem INTEGER, INTENT(IN) :: n @@ -245,13 +318,10 @@ CONTAINS routineP = moduleN//':'//routineN INTEGER :: error_handle - TYPE(dbcsr_error_type) :: my_error ! --------------------------------------------------------------------------- - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_set (routineN, error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_set(routineN, error_handle, error) SELECT CASE (dbcsr_cuda_dev_mem_get_type (dev_mem)) CASE (dbcsr_type_int_4) @@ -273,19 +343,16 @@ CONTAINS CALL dbcsr_cuda_dev_mem_alloc (dev_mem%d_z, n,& error=error, stat=stat) CASE default - IF (PRESENT (error)) my_error = error - CALL dbcsr_assert (.FALSE.,& - dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& - "Invalid data type", __LINE__, error=my_error) - IF (PRESENT (error)) error = my_error + STOP "dev_mem_alloc_any: Invalid data type" END SELECT - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_stop (error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dev_mem_alloc_any +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_any (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type), INTENT(INOUT) :: dev_mem INTEGER, INTENT(IN) :: n @@ -297,13 +364,10 @@ CONTAINS routineP = moduleN//':'//routineN INTEGER :: error_handle - TYPE(dbcsr_error_type) :: my_error ! --------------------------------------------------------------------------- - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_set (routineN, error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_set(routineN, error_handle, error) SELECT CASE (dbcsr_cuda_dev_mem_get_type (dev_mem)) CASE (dbcsr_type_int_4) @@ -325,19 +389,16 @@ CONTAINS CALL dbcsr_cuda_dev_mem_realloc (dev_mem%d_z, n,& error=error, stat=stat) CASE default - IF (PRESENT (error)) my_error = error - CALL dbcsr_assert (.FALSE.,& - dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& - "Invalid data type", __LINE__, error=my_error) - IF (PRESENT (error)) error = my_error + STOP "dev_mem_realloc_any: Invalid data type" END SELECT - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_stop (error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dev_mem_realloc_any +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_any (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), & @@ -348,13 +409,10 @@ CONTAINS routineP = moduleN//':'//routineN INTEGER :: error_handle - TYPE(dbcsr_error_type) :: my_error ! --------------------------------------------------------------------------- - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_set (routineN, error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_set(routineN, error_handle, error) SELECT CASE (dbcsr_cuda_dev_mem_get_type (dev_mem)) CASE (dbcsr_type_int_4) @@ -376,19 +434,16 @@ CONTAINS CALL dbcsr_cuda_dev_mem_dealloc (dev_mem%d_z,& error=error, stat=stat) CASE default - IF (PRESENT (error)) my_error = error - CALL dbcsr_assert (.FALSE.,& - dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& - "Invalid data type", __LINE__, error=my_error) - IF (PRESENT (error)) error = my_error + STOP "dev_mem_dealloc_any: Invalid data type" END SELECT - IF (PRESENT (error)) my_error = error - CALL dbcsr_error_stop (error_handle, my_error) - IF (PRESENT (error)) error = my_error + IF (PRESENT (error)) CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE dev_mem_dealloc_any +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_any (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type), INTENT(INOUT) :: dev_mem INTEGER, INTENT(IN) :: first, last diff --git a/src/dbcsr_lib/dbcsr_cuda_memory__nametype1_.template b/src/dbcsr_lib/dbcsr_cuda_memory__nametype1_.template index ed2916abc7..cb1b66cb6d 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory__nametype1_.template +++ b/src/dbcsr_lib/dbcsr_cuda_memory__nametype1_.template @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_[nametype1] (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_[shorttype1]), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_[nametype1]: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_[nametype1] +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_[nametype1] (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_[shorttype1]), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_[nametype1]: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_[nametype1] +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_[nametype1] (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_[shorttype1]), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_[nametype1]: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_[nametype1] - SUBROUTINE host_mem_alloc_[nametype1] (host_mem, n, write_combined, all_contexts, error, stat) - [type1], DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_[nametype1] (host_mem, n, error) + [type1], DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_[nametype1]', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*[bytes1], KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*[bytes1], error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_[nametype1] - SUBROUTINE host_mem_dealloc_[nametype1] (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_[nametype1]_2D (host_mem, n1, n2, error) + [type1], DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*[bytes1] + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_[nametype1]_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_[nametype1]_4D (host_mem, n1, n2, n3, n4, error) + [type1], DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*[bytes1] + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_[nametype1]_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_[nametype1] (host_mem, error) [type1], DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_[nametype1]', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - [type1], POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_[nametype1]: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_[nametype1]: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_[nametype1] +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_[nametype1]_2D (host_mem, error) + [type1], DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_[nametype1]_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_[nametype1]_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_[nametype1]: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_[nametype1]_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_[nametype1]_4D (host_mem, error) + [type1], DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_[nametype1]_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_[nametype1]_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_[nametype1]: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_[nametype1]_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_[nametype1] (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_[shorttype1]), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_c.F b/src/dbcsr_lib/dbcsr_cuda_memory_c.F index 31b0492854..5d03818dd3 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_c.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_c.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_c (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_c4), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_c: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_c +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_c (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_c4), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_c: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_c +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_c (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_c4), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_c: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_c - SUBROUTINE host_mem_alloc_c (host_mem, n, write_combined, all_contexts, error, stat) - COMPLEX(kind=real_4), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_c (host_mem, n, error) + COMPLEX(kind=real_4), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_c', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*(2*real_4_size), KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*(2*real_4_size), error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_c - SUBROUTINE host_mem_dealloc_c (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_c_2D (host_mem, n1, n2, error) + COMPLEX(kind=real_4), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*(2*real_4_size) + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_c_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_c_4D (host_mem, n1, n2, n3, n4, error) + COMPLEX(kind=real_4), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*(2*real_4_size) + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_c_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_c (host_mem, error) COMPLEX(kind=real_4), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_c', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - COMPLEX(kind=real_4), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_c: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_c: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_c +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_c_2D (host_mem, error) + COMPLEX(kind=real_4), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_c_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_c_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_c: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_c_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_c_4D (host_mem, error) + COMPLEX(kind=real_4), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_c_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_c_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_c: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_c_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_c (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_c4), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_d.F b/src/dbcsr_lib/dbcsr_cuda_memory_d.F index 69cfa6242e..96321acedb 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_d.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_d.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_d (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_r8), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_d: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_d +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_d (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_r8), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_d: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_d +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_d (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_r8), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_d: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_d - SUBROUTINE host_mem_alloc_d (host_mem, n, write_combined, all_contexts, error, stat) - REAL(kind=real_8), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_d (host_mem, n, error) + REAL(kind=real_8), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_d', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*real_8_size, KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*real_8_size, error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_d - SUBROUTINE host_mem_dealloc_d (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_d_2D (host_mem, n1, n2, error) + REAL(kind=real_8), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*real_8_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_d_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_d_4D (host_mem, n1, n2, n3, n4, error) + REAL(kind=real_8), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*real_8_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_d_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_d (host_mem, error) REAL(kind=real_8), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_d', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - REAL(kind=real_8), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_d: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_d: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_d +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_d_2D (host_mem, error) + REAL(kind=real_8), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_d_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_d_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_d: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_d_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_d_4D (host_mem, error) + REAL(kind=real_8), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_d_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_d_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_d: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_d_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_d (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_r8), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_i.F b/src/dbcsr_lib/dbcsr_cuda_memory_i.F index 7c064f1e8b..86ded090c4 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_i.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_i.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_i (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_i4), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_i: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_i +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_i (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_i4), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_i: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_i +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_i (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_i4), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_i: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_i - SUBROUTINE host_mem_alloc_i (host_mem, n, write_combined, all_contexts, error, stat) - INTEGER(KIND=int_4), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_i (host_mem, n, error) + INTEGER(KIND=int_4), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_i', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*int_4_size, KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*int_4_size, error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_i - SUBROUTINE host_mem_dealloc_i (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_i_2D (host_mem, n1, n2, error) + INTEGER(KIND=int_4), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*int_4_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_i_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_i_4D (host_mem, n1, n2, n3, n4, error) + INTEGER(KIND=int_4), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*int_4_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_i_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_i (host_mem, error) INTEGER(KIND=int_4), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_i', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - INTEGER(KIND=int_4), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_i: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_i: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_i +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_i_2D (host_mem, error) + INTEGER(KIND=int_4), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_i_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_i_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_i: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_i_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_i_4D (host_mem, error) + INTEGER(KIND=int_4), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_i_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_i_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_i: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_i_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_i (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_i4), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_l.F b/src/dbcsr_lib/dbcsr_cuda_memory_l.F index ed1061edaf..71163bc08e 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_l.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_l.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_l (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_i8), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_l: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_l +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_l (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_i8), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_l: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_l +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_l (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_i8), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_l: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_l - SUBROUTINE host_mem_alloc_l (host_mem, n, write_combined, all_contexts, error, stat) - INTEGER(KIND=int_8), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_l (host_mem, n, error) + INTEGER(KIND=int_8), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_l', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*int_8_size, KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*int_8_size, error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_l - SUBROUTINE host_mem_dealloc_l (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_l_2D (host_mem, n1, n2, error) + INTEGER(KIND=int_8), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*int_8_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_l_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_l_4D (host_mem, n1, n2, n3, n4, error) + INTEGER(KIND=int_8), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*int_8_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_l_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_l (host_mem, error) INTEGER(KIND=int_8), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_l', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - INTEGER(KIND=int_8), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_l: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_l: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_l +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_l_2D (host_mem, error) + INTEGER(KIND=int_8), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_l_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_l_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_l: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_l_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_l_4D (host_mem, error) + INTEGER(KIND=int_8), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_l_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_l_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_l: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_l_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_l (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_i8), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_r.F b/src/dbcsr_lib/dbcsr_cuda_memory_r.F index b6f76ecb1e..cdf0275f7e 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_r.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_r.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_r (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_r4), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_r: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_r +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_r (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_r4), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_r: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_r +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_r (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_r4), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_r: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_r - SUBROUTINE host_mem_alloc_r (host_mem, n, write_combined, all_contexts, error, stat) - REAL(kind=real_4), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_r (host_mem, n, error) + REAL(kind=real_4), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_r', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*real_4_size, KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*real_4_size, error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_r - SUBROUTINE host_mem_dealloc_r (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_r_2D (host_mem, n1, n2, error) + REAL(kind=real_4), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*real_4_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_r_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_r_4D (host_mem, n1, n2, n3, n4, error) + REAL(kind=real_4), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*real_4_size + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_r_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_r (host_mem, error) REAL(kind=real_4), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_r', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - REAL(kind=real_4), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_r: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_r: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_r +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_r_2D (host_mem, error) + REAL(kind=real_4), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_r_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_r_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_r: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_r_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_r_4D (host_mem, error) + REAL(kind=real_4), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_r_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_r_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_r: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_r_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_r (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_r4), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_memory_z.F b/src/dbcsr_lib/dbcsr_cuda_memory_z.F index 9235f5f063..2a57289532 100644 --- a/src/dbcsr_lib/dbcsr_cuda_memory_z.F +++ b/src/dbcsr_lib/dbcsr_cuda_memory_z.F @@ -3,6 +3,9 @@ ! Copyright (C) 2000 - 2013 Urban Borstnik and the CP2K developers group ! !-----------------------------------------------------------------------------! +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_alloc_z (dev_mem, n, error, stat) TYPE(dbcsr_cuda_mem_type_c8), & INTENT(OUT) :: dev_mem @@ -28,18 +31,16 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_alloc_z: Could not allocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_alloc_z +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_dealloc_z (dev_mem, error, stat) TYPE(dbcsr_cuda_mem_type_c8), INTENT(INOUT) :: dev_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error @@ -63,19 +64,16 @@ ELSE istat = 0 ENDIF - IF (istat /= 0) THEN - IF (PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not deallocate GPU device memory",& - __LINE__, error=error) - ENDIF - ENDIF + IF (istat /= 0) & + STOP "dev_mem_dealloc_z: Could not deallocate GPU device memory" IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_dealloc_z +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_realloc_z (dev_mem, n, error, stat, memory_crunch) TYPE(dbcsr_cuda_mem_type_c8), & INTENT(INOUT) :: dev_mem @@ -112,108 +110,134 @@ #endif IF (istat /= 0) THEN dev_mem%len = -1 - IF (PRESENT(error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not reallocate GPU device memory",& - __LINE__, error=error) - ENDIF + STOP "dev_mem_realloc_z: Could not reallocate GPU device memory" ENDIF IF (PRESENT (stat)) stat = istat IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dev_mem_realloc_z - SUBROUTINE host_mem_alloc_z (host_mem, n, write_combined, all_contexts, error, stat) - COMPLEX(kind=real_8), DIMENSION(:), & - POINTER :: host_mem +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_z (host_mem, n, error) + COMPLEX(kind=real_8), DIMENSION(:), POINTER :: host_mem INTEGER, INTENT(IN) :: n - LOGICAL, INTENT(IN), OPTIONAL :: write_combined, all_contexts TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_alloc_z', & - routineP = moduleN//':'//routineN - - INTEGER :: error_handle, istat - INTEGER(KIND=c_int) :: all_flag, wc_flag TYPE(C_PTR) :: host_mem_c_ptr -! --------------------------------------------------------------------------- - - IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) - IF (PRESENT (write_combined)) THEN - wc_flag = 1 - ELSE - wc_flag = 0 - ENDIF - IF (PRESENT (all_contexts)) THEN - all_flag = 1 - ELSE - all_flag = 0 - ENDIF -#if defined (__DBCSR_CUDA) - istat = cuda_host_mem_alloc_cu(host_mem_c_ptr,& - INT(MAX(1,n)*(2*real_8_size), KIND=C_SIZE_T),& - wc_flag, all_flag) -#else - istat = -1 -#endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Could not allocate host pinned memory",& - __LINE__, error=error) - NULLIFY (host_mem) - ELSE -#if defined (__DBCSR_CUDA) - CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) -#endif - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + CALL host_mem_alloc_raw(host_mem_c_ptr, MAX(1,n)*(2*real_8_size), error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n) /)) END SUBROUTINE host_mem_alloc_z - SUBROUTINE host_mem_dealloc_z (host_mem, error, stat) +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_z_2D (host_mem, n1, n2, error) + COMPLEX(kind=real_8), DIMENSION(:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*(2*real_8_size) + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, (/ MAX(1,n1),MAX(1,n2) /)) + END SUBROUTINE host_mem_alloc_z_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_alloc_z_4D (host_mem, n1, n2, n3, n4, error) + COMPLEX(kind=real_8), DIMENSION(:,:,:,:), POINTER :: host_mem + INTEGER, INTENT(IN) :: n1, n2, n3, n4 + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + TYPE(C_PTR) :: host_mem_c_ptr + INTEGER :: n_bytes + n_bytes = MAX(1,n1)*MAX(1,n2)*MAX(1,n3)*MAX(1,n4)*(2*real_8_size) + CALL host_mem_alloc_raw(host_mem_c_ptr,n_bytes , error) + CALL C_F_POINTER (host_mem_c_ptr, host_mem, & + (/ MAX(1,n1),MAX(1,n2),MAX(1,n3),MAX(1,n4) /)) + END SUBROUTINE host_mem_alloc_z_4D + + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_z (host_mem, error) COMPLEX(kind=real_8), DIMENSION(:), & POINTER :: host_mem TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error - INTEGER, INTENT(OUT), OPTIONAL :: stat - CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_z', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, istat - COMPLEX(kind=real_8), POINTER :: host_first_el - TYPE(C_PTR) :: host_mem_c_ptr - -! --------------------------------------------------------------------------- + IF (SIZE (host_mem) == 0) RETURN IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) #if defined (__DBCSR_CUDA) - IF (SIZE (host_mem) .GT. 0) THEN - host_first_el => host_mem(1) - host_mem_c_ptr = C_LOC (host_first_el) - ENDIF - IF (SIZE (host_mem) .GT. 0) THEN - istat = cuda_host_mem_dealloc_cu (host_mem_c_ptr) - ENDIF + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_z: Error deallocating host pinned memory" #else - istat = -1 + STOP "host_mem_dealloc_z: DBCSR_CUDA not compiled in." #endif - IF (istat /= 0 .AND. PRESENT (error)) THEN - CALL dbcsr_assert (istat, "EQ", 0,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Error deallocating host pinned memory",& - __LINE__, error=error) - ENDIF - IF (PRESENT (stat)) stat = istat - IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE host_mem_dealloc_z +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_z_2D (host_mem, error) + COMPLEX(kind=real_8), DIMENSION(:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_z_2D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_z_2D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_z: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_z_2D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** + SUBROUTINE host_mem_dealloc_z_4D (host_mem, error) + COMPLEX(kind=real_8), DIMENSION(:,:,:,:), & + POINTER :: host_mem + TYPE(dbcsr_error_type), INTENT(INOUT), OPTIONAL :: error + CHARACTER(len=*), PARAMETER :: routineN = 'host_mem_dealloc_z_4D', & + routineP = moduleN//':'//routineN + INTEGER :: error_handle, istat + + IF (SIZE (host_mem) == 0) RETURN + IF (PRESENT (error)) CALL dbcsr_error_set (routineN, error_handle, error) +#if defined (__DBCSR_CUDA) + istat = cuda_host_mem_dealloc_cu(C_LOC(host_mem(1,1,1,1))) + IF (istat /= 0 ) & + STOP "host_mem_dealloc_z_4D: Error deallocating host pinned memory" +#else + STOP "host_mem_dealloc_z: DBCSR_CUDA not compiled in." +#endif + IF (PRESENT (error)) CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE host_mem_dealloc_z_4D + + +! ***************************************************************************** +!> \brief +! ***************************************************************************** SUBROUTINE dev_mem_zero_z (dev_mem, first, last, error) TYPE(dbcsr_cuda_mem_type_c8), & INTENT(INOUT) :: dev_mem diff --git a/src/dbcsr_lib/dbcsr_cuda_types.F b/src/dbcsr_lib/dbcsr_cuda_types.F index 485435532b..60fca2717e 100644 --- a/src/dbcsr_lib/dbcsr_cuda_types.F +++ b/src/dbcsr_lib/dbcsr_cuda_types.F @@ -32,7 +32,10 @@ MODULE dbcsr_cuda_types PUBLIC :: dbcsr_cuda_mem_type_i4, dbcsr_cuda_mem_type_i8,& dbcsr_cuda_mem_type_r4, dbcsr_cuda_mem_type_r8,& dbcsr_cuda_mem_type_c4, dbcsr_cuda_mem_type_c8 + + PUBLIC :: dbcsr_cuda_mem_p_type + ! TODO: these datastructures are pointless. They hold C_PTR anyways. TYPE dbcsr_cuda_mem_type_i4 TYPE(C_PTR) :: ref INTEGER :: len, req_len @@ -74,7 +77,10 @@ MODULE dbcsr_cuda_types TYPE(dbcsr_cuda_mem_type_c8) :: d_z INTEGER :: refcount END TYPE dbcsr_cuda_mem_type - - + + + TYPE dbcsr_cuda_mem_p_type + TYPE(dbcsr_cuda_mem_type), POINTER :: p + END TYPE dbcsr_cuda_mem_p_type END MODULE dbcsr_cuda_types diff --git a/src/dbcsr_lib/dbcsr_data_methods.F b/src/dbcsr_lib/dbcsr_data_methods.F index ece6cc93df..b548621742 100644 --- a/src/dbcsr_lib/dbcsr_data_methods.F +++ b/src/dbcsr_lib/dbcsr_data_methods.F @@ -292,17 +292,13 @@ CONTAINS CASE (dbcsr_memory_CUDA_host_pinned) SELECT CASE (data_type) CASE (dbcsr_type_real_4) - CALL dbcsr_cuda_host_mem_alloc (area%r_sp, sizes(1), stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_alloc (area%r_sp, sizes(1), error=error) CASE (dbcsr_type_real_8) - CALL dbcsr_cuda_host_mem_alloc (area%r_dp, sizes(1), stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_alloc (area%r_dp, sizes(1), error=error) CASE (dbcsr_type_complex_4) - CALL dbcsr_cuda_host_mem_alloc (area%c_sp, sizes(1), stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_alloc (area%c_sp, sizes(1), error=error) CASE (dbcsr_type_complex_8) - CALL dbcsr_cuda_host_mem_alloc (area%c_dp, sizes(1), stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_alloc (area%c_dp, sizes(1), error=error) CASE (dbcsr_type_real_8_2d, dbcsr_type_real_4_2d,& dbcsr_type_complex_8_2d, dbcsr_type_complex_4_2d) CALL dbcsr_assert (.FALSE.,& @@ -399,20 +395,16 @@ CONTAINS CASE (dbcsr_memory_CUDA_host_pinned) SELECT CASE (data_type) CASE (dbcsr_type_real_4) - CALL dbcsr_cuda_host_mem_dealloc (area%r_sp, stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_dealloc (area%r_sp, error=error) NULLIFY (area%r_sp) CASE (dbcsr_type_real_8) - CALL dbcsr_cuda_host_mem_dealloc (area%r_dp, stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_dealloc (area%r_dp, error=error) NULLIFY (area%r_dp) CASE (dbcsr_type_complex_4) - CALL dbcsr_cuda_host_mem_dealloc (area%c_sp, stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_dealloc (area%c_sp, error=error) NULLIFY (area%c_sp) CASE (dbcsr_type_complex_8) - CALL dbcsr_cuda_host_mem_dealloc (area%c_dp, stat=stat,& - error=error) + CALL dbcsr_cuda_host_mem_dealloc (area%c_dp, error=error) NULLIFY (area%c_dp) CASE (dbcsr_type_real_8_2d, dbcsr_type_real_4_2d,& dbcsr_type_complex_8_2d, dbcsr_type_complex_4_2d) diff --git a/src/dbcsr_lib/dbcsr_mm_cannon.F b/src/dbcsr_lib/dbcsr_mm_cannon.F index 740564903a..74977b3eb1 100644 --- a/src/dbcsr_lib/dbcsr_mm_cannon.F +++ b/src/dbcsr_lib/dbcsr_mm_cannon.F @@ -63,10 +63,12 @@ MODULE dbcsr_mm_cannon dbcsr_mp_numnodes, dbcsr_mp_pgrid, dbcsr_nblkcols_local, & dbcsr_nblkcols_total, dbcsr_nblkrows_local, dbcsr_nblkrows_total, & dbcsr_nfullcols_local, dbcsr_nfullrows_local, dbcsr_valid_index - USE dbcsr_mm_multrec, ONLY: dbcsr_multrec_finalize,& - dbcsr_multrec_init,& - dbcsr_multrec_sparse - USE dbcsr_mm_types, ONLY: carrier_type + USE dbcsr_mm_multrec, ONLY: dbcsr_mm_multrec_finalize,& + dbcsr_mm_multrec_init,& + dbcsr_mm_multrec_lib_finalize,& + dbcsr_mm_multrec_lib_init,& + dbcsr_mm_multrec_multiply + USE dbcsr_mm_types, ONLY: multrec_carrier_type USE dbcsr_mp_operations, ONLY: dbcsr_irecv_any,& dbcsr_isend_any,& dbcsr_mp_type_from_anytype @@ -91,10 +93,33 @@ MODULE dbcsr_mm_cannon LOGICAL, PARAMETER :: debug_mod = .FALSE. LOGICAL, PARAMETER :: careful_mod = .FALSE. - PUBLIC :: dbcsr_mult_m_e_e + + PUBLIC :: dbcsr_mm_cannon_lib_init, dbcsr_mm_cannon_lib_finalize + PUBLIC :: dbcsr_mm_cannon_multiply -CONTAINS + CONTAINS + +! ***************************************************************************** +! \brief Initialize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_cannon_lib_init(error) + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CALL dbcsr_mm_multrec_lib_init(error) + END SUBROUTINE + + +! ***************************************************************************** +! \brief Finalize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_cannon_lib_finalize(error) + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CALL dbcsr_mm_multrec_lib_finalize(error) + END SUBROUTINE ! ***************************************************************************** @@ -108,7 +133,7 @@ CONTAINS !> existing product matrix; default is no !> \param[out] flop (optional) effective flop ! ***************************************************************************** - SUBROUTINE dbcsr_mult_m_e_e (left_set, right_set, product_matrix,& + SUBROUTINE dbcsr_mm_cannon_multiply(left_set, right_set, product_matrix,& error, retain_sparsity, & filter_eps, flop) TYPE(dbcsr_2d_array_type), POINTER :: left_set, right_set @@ -118,7 +143,7 @@ CONTAINS REAL(kind=real_8), INTENT(in), OPTIONAL :: filter_eps INTEGER(KIND=int_8), INTENT(OUT) :: flop - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mult_m_e_e', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_cannon_multiply', & routineP = moduleN//':'//routineN CHARACTER(LEN=80), PARAMETER :: & fdata = '(A,1X,I4,"(",2(I3),"x",2(I3),")","(",I3,"x",I3,")")', fxfer = & @@ -179,7 +204,6 @@ CONTAINS right_fill REAL(kind=sp), ALLOCATABLE, DIMENSION(:) :: left_norms, right_norms, & row_max_epss - TYPE(carrier_type), SAVE :: carrier TYPE(dbcsr_2d_array_type), POINTER :: left_buffer_1, left_buffer_2, & left_buffer_calc, left_buffer_comm, right_buffer_1, right_buffer_2, & right_buffer_calc, right_buffer_comm @@ -199,8 +223,9 @@ CONTAINS left_send_subtypes, & right_recv_subtypes, & right_send_subtypes + TYPE(multrec_carrier_type), SAVE :: multrec_carrier -!$OMP THREADPRIVATE (carrier) +!$OMP THREADPRIVATE (multrec_carrier) ! --------------------------------------------------------------------------- @@ -659,13 +684,11 @@ CONTAINS !$omp right_data_sr, right_data_rr, left_data_sr, left_data_rr,& !$omp right_index_sr, right_index_rr, left_index_sr, left_index_rr), & !$omp shared (a_dev, b_dev) firstprivate (error) - CALL dbcsr_multrec_init(& + CALL dbcsr_mm_multrec_init(& left_buffer_comm%mats(1, 1)%m,& right_buffer_comm%mats(1, 1)%m,& product_matrix%m,& - carrier,& - right_data_sr, right_data_rr, left_data_sr, left_data_rr,& - right_index_sr, right_index_rr, left_index_sr, left_index_rr, & + multrec_carrier,& keep_sparsity=keep_sparsity,& eps=filter_eps,& row_max_epss = row_max_epss,& @@ -1042,16 +1065,15 @@ CONTAINS !$omp reduction (+: flop_single) t_error=error CALL dbcsr_error_set(routineN//"_multrec_sparse", error_handler2, t_error) - CALL dbcsr_multrec_sparse(& + CALL dbcsr_mm_multrec_multiply(& left_buffer_calc%mats(1, v_ki+1)%m,& right_buffer_calc%mats(v_ki+1, 1)%m,& product_matrix%m,& - carrier,& - keep_sparsity=keep_sparsity,& + multrec_carrier,& + keep_sparsity=keep_sparsity,& flop=flop_single,& a_norms=left_norms, b_norms=right_norms,& - eps=filter_eps,& - row_max_epss = row_max_epss, error=t_error) + error=t_error) ! once multiplication is complete, thread zero polls MPI until ! all other threads have also completed !$omp atomic @@ -1062,7 +1084,14 @@ CONTAINS !$ nthreads = omp_get_num_threads() IF (use_comm_thread .AND. (ithread .EQ. 0)) THEN DO WHILE (threads_finished .NE. nthreads) - CALL progress_comms(carrier) + CALL mp_testany(right_data_sr) + CALL mp_testany(right_data_rr) + CALL mp_testany(left_data_sr) + CALL mp_testany(left_data_rr) + CALL mp_testany(right_index_sr) + CALL mp_testany(right_index_rr) + CALL mp_testany(left_index_sr) + CALL mp_testany(left_index_rr) !$omp flush (threads_finished) END DO END IF @@ -1097,14 +1126,14 @@ CONTAINS ! -!$omp parallel & +!$omp parallel & !$omp default (none) & !$omp private (t_error) & !$omp shared (product_matrix, error) ! t_error = error ! Finalize multiplication - CALL dbcsr_multrec_finalize (carrier, product_matrix%m, t_error) + CALL dbcsr_mm_multrec_finalize(multrec_carrier, product_matrix%m, t_error) !$omp end parallel ! IF (ALLOCATED (right_norms)) THEN @@ -1181,7 +1210,7 @@ CONTAINS i = real_8_size * 2 END SELECT CALL dbcsr_error_stop(error_handler, error) - END SUBROUTINE dbcsr_mult_m_e_e + END SUBROUTINE dbcsr_mm_cannon_multiply ! ****************************************************************************** @@ -1726,24 +1755,6 @@ CONTAINS CALL dbcsr_error_stop(error_handle, error) END SUBROUTINE calculate_norms - - -! ***************************************************************************** -!> \brief Call in MPI to progrss any outstanding communications -! ***************************************************************************** - SUBROUTINE progress_comms(carrier) - TYPE(carrier_type), INTENT(inout) :: carrier - - CALL mp_testany(carrier%right_data_sr) - CALL mp_testany(carrier%right_data_rr) - CALL mp_testany(carrier%left_data_sr) - CALL mp_testany(carrier%left_data_rr) - CALL mp_testany(carrier%right_index_sr) - CALL mp_testany(carrier%right_index_rr) - CALL mp_testany(carrier%left_index_sr) - CALL mp_testany(carrier%left_index_rr) - END SUBROUTINE - #include "dbcsr_mm_cannon_d.F" #include "dbcsr_mm_cannon_z.F" #include "dbcsr_mm_cannon_s.F" diff --git a/src/dbcsr_lib/dbcsr_mm_csr.F b/src/dbcsr_lib/dbcsr_mm_csr.F index ae6d306ce2..d2544935cd 100644 --- a/src/dbcsr_lib/dbcsr_mm_csr.F +++ b/src/dbcsr_lib/dbcsr_mm_csr.F @@ -5,9 +5,9 @@ ! ***************************************************************************** !> \brief Third layer of the dbcsr matrix-matrix multiplication. -!> It collects the full matrix blocks, which need to be multiplied, +!> It collects the full matrix blocks, which need to be multiplied, !> and stores their parameters in various stacks. -!> After a certain amount of parameters is collected it dispatches +!> After a certain amount of parameters is collected it dispatches !> the filled stacks to either the CPU or the GPU. !> !> \author Urban Borstnik @@ -16,341 +16,466 @@ !> - 2010-02-23 Moved from dbcsr_operations !> - 2011-11 Moved parameter-stack processing routines to !> dbcsr_mm_methods. -!> - 2013-01 reorganized code (Ole Schuett) +!> - 2013-01 extensive refactoring (Ole Schuett) ! ***************************************************************************** MODULE dbcsr_mm_csr USE array_types, ONLY: array_data USE dbcsr_config, ONLY: dbcsr_get_conf_nstacks,& - mm_async,& mm_driver,& - mm_driver_cuda,& - mm_host_driver,& - mm_stack_size,& - mm_thread_workshare,& - use_comm_thread + mm_host_driver USE dbcsr_error_handling USE dbcsr_kinds, ONLY: int_1,& int_4,& int_8,& real_8,& sp - USE dbcsr_message_passing, ONLY: mp_testany - USE dbcsr_mm_driver, ONLY: dbcsr_mm_driver_inner_init,& + USE dbcsr_mm_driver, ONLY: dbcsr_mm_driver_inner_finalize,& + dbcsr_mm_driver_inner_init,& + dbcsr_mm_driver_lib_finalize,& + dbcsr_mm_driver_lib_init,& dbcsr_mm_driver_outer_finalize,& - dbcsr_mm_driver_outer_init - USE dbcsr_mm_stack, ONLY: enqueue_ps_group,& - get_stack_or_process_queue,& - process_queue_mine,& - process_queue_others,& - process_queue_preempt - USE dbcsr_mm_types, ONLY: carrier_type,& - ele_type,& - hash_table_type - USE dbcsr_pq_methods, ONLY: & - dbcsr_pq_create, dbcsr_pq_destroy, dbcsr_pq_flush_level_chg, & - dbcsr_pq_handoff_level_chg, dbcsr_pq_mark_done, dbcsr_pq_refresh, & - dbcsr_pq_share, dbcsr_pq_unshare, dbcsr_ps_set_advance, & - dbcsr_ps_set_create, dbcsr_ps_set_destroy, dbcsr_ps_set_get_group_p, & - dbcsr_ps_set_get_n_working, dbcsr_ps_target_add_data, & - dbcsr_ps_target_new, dbcsr_ps_target_release, dbcsr_psg_add_data_ab, & - dbcsr_psg_get_state, dbcsr_psg_rm_data_ab, dbcsr_psg_view_close, & - dbcsr_psg_view_open - USE dbcsr_pq_types, ONLY: & - dbcsr_pq_type, dbcsr_ps_group_type, dbcsr_ps_set_type, & - dbcsr_ps_state_queued, dbcsr_ps_target_obj, dbcsr_ps_width, p_a_first, & - p_b_first, p_c_blk, p_c_first, p_k, p_m, p_n + dbcsr_mm_driver_outer_init,& + dbcsr_mm_driver_process_stack + USE dbcsr_mm_types, ONLY: & + csr_carrier_type, dbcsr_ps_state_empty, dbcsr_ps_state_working, & + ele_type, hash_table_type, p_a_first, p_b_first, p_c_blk, p_c_first, & + p_k, p_m, p_n, stack_descriptor_type USE dbcsr_ptr_util, ONLY: ensure_array_size USE dbcsr_toollib, ONLY: sort - USE dbcsr_types, ONLY: dbcsr_memory_CUDA_host_pinned,& - dbcsr_memory_default,& - dbcsr_type + USE dbcsr_types, ONLY: dbcsr_type USE dbcsr_util, ONLY: map_most_common !$ USE OMP_LIB - + IMPLICIT NONE - + PRIVATE - + CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbcsr_mm_csr' LOGICAL, PARAMETER :: debug_mod = .FALSE. LOGICAL, PARAMETER :: careful_mod = .FALSE. + REAL, PARAMETER :: default_resize_factor = 1.618034 - !> \var max_stack_block_size The maximal block size to be specially !> treated. INTEGER, PARAMETER :: max_stack_block_size = HUGE (INT (0)) - - REAL, PARAMETER :: default_resize_factor = 1.618034 - - - PUBLIC :: csr_multiply_outer_init, csr_multiply_outer_finalize - PUBLIC :: csr_multiply_inner_init, csr_multiply_inner_finalize - PUBLIC :: csr_multiply_unwrap - - + + + PUBLIC :: dbcsr_mm_csr_lib_init, dbcsr_mm_csr_lib_finalize + PUBLIC :: dbcsr_mm_csr_outer_init, dbcsr_mm_csr_outer_finalize + PUBLIC :: dbcsr_mm_csr_inner_init, dbcsr_mm_csr_inner_finalize + PUBLIC :: dbcsr_mm_csr_multiply + + CONTAINS ! ***************************************************************************** -!> \brief Performs multiplication of smaller submatrices. -!> -!> This routine is used for setting up and calling csr_multiply with -!> as few argument indirections as possible. +! \brief Initialize the library +! \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply_unwrap(mi, mf, ni, nf, ki, kf,& - ai, af, a_index, bi, bf, b_index, & - carrier, error) - INTEGER, INTENT(IN) :: mi, mf, ni, nf, ki, kf, ai, af - INTEGER, DIMENSION(1:3, 1:af), & - INTENT(IN) :: a_index - INTEGER, INTENT(IN) :: bi, bf - INTEGER, DIMENSION(1:3, 1:bf), & - INTENT(IN) :: b_index - TYPE(carrier_type), INTENT(INOUT) :: carrier + SUBROUTINE dbcsr_mm_csr_lib_init(error) TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'csr_multiply_unwrap', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: dbg = .FALSE. + CALL dbcsr_mm_driver_lib_init(error) + END SUBROUTINE + + +! ***************************************************************************** +! \brief Finalize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_csr_lib_finalize(error) + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CALL dbcsr_mm_driver_lib_finalize(error) + END SUBROUTINE + + +! ***************************************************************************** +! \brief A wrapper around dbcsr_mm_csr_multiply_low to avoid expensive dereferencings. +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_csr_multiply(mi, mf, ni, nf, ki, kf,& + ai, af,& + bi, bf,& + m_sizes, n_sizes, k_sizes,& + c_local_rows, c_local_cols,& + c_has_symmetry, keep_sparsity, use_eps,& + row_max_epss,& + flop,& + a_index, b_index, a_norms, b_norms,& + product, csr_carrier, error) + INTEGER, INTENT(IN) :: mi, mf, ni, nf, ki, kf, ai, & + af, bi, bf + INTEGER, DIMENSION(:), INTENT(INOUT) :: m_sizes, n_sizes, k_sizes, & + c_local_rows, c_local_cols + LOGICAL, INTENT(INOUT) :: c_has_symmetry, & + keep_sparsity, use_eps + REAL(kind=sp), DIMENSION(:) :: row_max_epss + INTEGER(KIND=int_8), INTENT(INOUT) :: flop + INTEGER, DIMENSION(1:3, 1:af), & + INTENT(IN) :: a_index + INTEGER, DIMENSION(1:3, 1:bf), & + INTENT(IN) :: b_index + REAL(KIND=sp), DIMENSION(:), POINTER :: a_norms, b_norms + TYPE(dbcsr_type), INTENT(INOUT) :: product + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier + TYPE(dbcsr_error_type), INTENT(INOUT) :: error INTEGER :: ithread, max_new_nblks, & - n_a_norms, n_b_norms, & - nblks_new, nstacks - INTEGER, ALLOCATABLE, DIMENSION(:) :: a_row_p, b_row_p - INTEGER, ALLOCATABLE, DIMENSION(:, :) :: a_blk_info, b_blk_info - LOGICAL :: advance_memreg - REAL(KIND=sp), DIMENSION(1:af-ai+1) :: csr_a_norms - REAL(KIND=sp), DIMENSION(1:bf-bi+1) :: csr_b_norms - TYPE(dbcsr_ps_group_type), POINTER :: ps_group + nblks_new + + ithread = 0 + !$ ithread = omp_get_thread_num() + + ! This has to be done here because ensure_array_size() expects a pointer. + ! the maximum number of blocks can be safely estimated by considering both the rowxcol, + ! but also the blocks the latter can never be larger than norec**2, which is a 'small' constant + max_new_nblks = MIN(INT(mf-mi+1,int_8) * INT(nf-ni+1,int_8), & + INT(af-ai+1,int_8) * INT(bf-bi+1,int_8)) + + nblks_new = product%wms(ithread+1)%lastblk + max_new_nblks + + CALL ensure_array_size(product%wms(ithread+1)%row_i, ub=nblks_new,& + factor=default_resize_factor, error=error) + CALL ensure_array_size(product%wms(ithread+1)%col_i, ub=nblks_new,& + factor=default_resize_factor, error=error) + CALL ensure_array_size(product%wms(ithread+1)%blk_p, ub=nblks_new,& + factor=default_resize_factor, error=error) + + CALL dbcsr_mm_csr_multiply_low(mi=mi, mf=mf,ni=ni, nf=nf, ki=ki, kf=kf,& + ai=ai, af=af,& + bi=bi, bf=bf,& + c_row_i=product%wms(ithread+1)%row_i,& + c_col_i=product%wms(ithread+1)%col_i,& + c_blk_p=product%wms(ithread+1)%blk_p,& + lastblk =product%wms(ithread+1)%lastblk, & + datasize=product%wms(ithread+1)%datasize,& + m_sizes=m_sizes, n_sizes=n_sizes, k_sizes=k_sizes,& + c_local_rows=c_local_rows, c_local_cols=c_local_cols,& + c_has_symmetry=c_has_symmetry, keep_sparsity=keep_sparsity,& + use_eps=use_eps,& + row_max_epss=row_max_epss,& + flop=flop,& + row_size_maps=csr_carrier%m_size_maps,& + col_size_maps=csr_carrier%n_size_maps,& + k_size_maps=csr_carrier%k_size_maps,& + row_size_maps_size=csr_carrier%m_size_maps_size,& + col_size_maps_size=csr_carrier%n_size_maps_size,& + k_size_maps_size=csr_carrier%k_size_maps_size,& + nm_stacks=csr_carrier%nm_stacks, nn_stacks=csr_carrier%nn_stacks,& + nk_stacks=csr_carrier%nk_stacks, & + stack_map=csr_carrier%stack_map,& + c_hashes=csr_carrier%c_hashes,& + a_index=a_index, b_index=b_index,& + a_norms=a_norms, b_norms=b_norms,& + csr_carrier=csr_carrier,& + error=error) + + END SUBROUTINE dbcsr_mm_csr_multiply + + +! ***************************************************************************** +!> \brief Performs multiplication of smaller submatrices. +! ***************************************************************************** + SUBROUTINE dbcsr_mm_csr_multiply_low(mi, mf, ni, nf, ki, kf,& + ai, af,& + bi, bf,& + c_hashes, c_row_i, c_col_i, c_blk_p, lastblk, datasize,& + m_sizes, n_sizes, k_sizes,& + c_local_rows, c_local_cols,& + c_has_symmetry, keep_sparsity, use_eps,& + row_size_maps, col_size_maps, k_size_maps,& + row_size_maps_size, col_size_maps_size, k_size_maps_size,& + nm_stacks, nn_stacks, nk_stacks, stack_map,& + row_max_epss, & + flop, a_index, b_index,a_norms, b_norms, csr_carrier, error) + INTEGER, INTENT(IN) :: mi, mf, ni, nf, ki, kf, ai, & + af, bi, bf + TYPE(hash_table_type), DIMENSION(:), & + INTENT(INOUT) :: c_hashes + INTEGER, DIMENSION(:), INTENT(INOUT) :: c_row_i, c_col_i, c_blk_p + INTEGER, INTENT(INOUT) :: lastblk, datasize + INTEGER, DIMENSION(:), INTENT(IN) :: m_sizes, n_sizes, k_sizes, & + c_local_rows, c_local_cols + LOGICAL, INTENT(IN) :: c_has_symmetry, & + keep_sparsity, use_eps + INTEGER, INTENT(IN) :: row_size_maps_size, & + k_size_maps_size, & + col_size_maps_size + INTEGER(KIND=int_4), & + DIMENSION(0:row_size_maps_size-1), & + INTENT(IN) :: row_size_maps + INTEGER(KIND=int_4), & + DIMENSION(0:col_size_maps_size-1), & + INTENT(IN) :: col_size_maps + INTEGER(KIND=int_4), & + DIMENSION(0:k_size_maps_size-1), & + INTENT(IN) :: k_size_maps + INTEGER, INTENT(IN) :: nm_stacks, nn_stacks, & + nk_stacks + INTEGER(KIND=int_1), DIMENSION(& + nn_stacks+1, nk_stacks+1, nm_stacks+1)& + , INTENT(IN) :: stack_map + REAL(kind=sp), DIMENSION(:) :: row_max_epss + INTEGER(KIND=int_8), INTENT(INOUT) :: flop + INTEGER, DIMENSION(1:3, 1:af), & + INTENT(IN) :: a_index + INTEGER, DIMENSION(1:3, 1:bf), & + INTENT(IN) :: b_index + REAL(KIND=sp), DIMENSION(:), POINTER :: a_norms, b_norms + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_csr_multiply_low', & + routineP = moduleN//':'//routineN + LOGICAL, PARAMETER :: dbg = .FALSE., & + local_timing = .FALSE. + + INTEGER :: a_blk, a_col_l, a_row_l, b_blk, b_col_l, c, c_blk_id, & + c_col_logical, c_nze, c_row_logical, ithread, k_size, m_size, & + mapped_col_size, mapped_k_size, mapped_row_size, n_a_norms, n_b_norms, & + n_size, nstacks, s_dp, ws + INTEGER, DIMENSION(mi:mf+1) :: a_row_p + INTEGER, DIMENSION(ki:kf+1) :: b_row_p + INTEGER, DIMENSION(:, :, :), POINTER :: stackcol_data + INTEGER, DIMENSION(:), POINTER :: stackcol_fillcount + INTEGER, DIMENSION(2, bf-bi+1) :: b_blk_info + INTEGER, DIMENSION(2, af-ai+1) :: a_blk_info + INTEGER(KIND=int_4) :: offset + LOGICAL :: block_exists, flush_stack + REAL(kind=sp) :: a_norm, a_row_eps, b_norm + REAL(KIND=sp), DIMENSION(1:af-ai+1) :: left_norms + REAL(KIND=sp), DIMENSION(1:bf-bi+1) :: right_norms ! --------------------------------------------------------------------------- - IF (dbg) THEN - WRITE(*,'(I7,1X,5(A,2(1X,I7)))')0,"uwr", mi, mf,",",ni,nf,",",ki,kf,"/",ai,af,",",bi,bf + ithread = 0 + !$ ithread = omp_get_thread_num() + + nstacks = SIZE(csr_carrier%stackgrid_data, 3) + + IF (use_eps) THEN + n_a_norms = af-ai+1 + n_b_norms = bf-bi+1 + ELSE + n_a_norms = 0 + n_b_norms = 0 ENDIF - IF (af-ai+1 .GT. 0 .AND. bf-bi+1 .GT. 0) THEN - ! the maximum number of blocks can be safely estimated by considering both the rowxcol, - ! but also the blocks the latter can never be larger than norec**2, which is a 'small' constant - max_new_nblks = MIN(INT(mf-mi+1,int_8) * INT(nf-ni+1,int_8), & - INT(af-ai+1,int_8) * INT(bf-bi+1,int_8)) - nblks_new = carrier%lastblk + max_new_nblks + ! + ! Build the indices + CALL build_csr_index (mi,mf,ai,af,a_row_p, a_blk_info, a_index,& + n_a_norms, left_norms, a_norms) + CALL build_csr_index (ki,kf,bi,bf,b_row_p, b_blk_info, b_index,& + n_b_norms, right_norms, b_norms) - CALL ensure_array_size(carrier%my_wm%row_i, ub=nblks_new,& - factor=default_resize_factor, error=error) - CALL ensure_array_size(carrier%my_wm%col_i, ub=nblks_new,& - factor=default_resize_factor, error=error) - CALL ensure_array_size(carrier%my_wm%blk_p, ub=nblks_new,& - factor=default_resize_factor, error=error) - ALLOCATE (a_row_p(mi:mf+1)) - ALLOCATE (b_row_p(ki:kf+1)) - ALLOCATE (a_blk_info(2,af-ai+1)) - ALLOCATE (b_blk_info(2,bf-bi+1)) - ! - IF (carrier%use_eps) THEN - n_a_norms = af-ai+1 - n_b_norms = bf-bi+1 - ELSE - n_a_norms = 0 - n_b_norms = 0 - ENDIF - ! - ! Build the indices - CALL build_csr_index (mi,mf,ai,af,a_row_p, a_blk_info, a_index,& - n_a_norms, csr_a_norms, carrier%a_norms) - CALL build_csr_index (ki,kf,bi,bf,b_row_p, b_blk_info, b_index,& - n_b_norms, csr_b_norms, carrier%b_norms) - ! - ! This is called here to get the ps_group, a parameter stack. - ! The memory region (of the parameter set) it belongs to must - ! remain unchanged throughout the csr_multiply call while the - ! buffer is allowed to change. The parameter stack groups of - ! all the buffers of a memory region share one "super parameter - ! stack" (\see dbcsr_ps_set_create). This super parameter - ! stack is passed directly to the csr_multiply routine - ! (ps_group%master%s%parameters) for efficiency reasons. - CALL get_stack_or_process_queue (carrier%param_sets, carrier%queue,& - ps_group, driver=mm_host_driver, error=error) - ! - nstacks = SIZE(ps_group%stacks) - CALL csr_multiply (mi, mf, ni, nf, ki, kf,& - ai, af, a_row_p, a_blk_info, bi, bf, b_row_p, b_blk_info,& - carrier%c_hashes,& - carrier%my_wm%row_i, carrier%my_wm%col_i, carrier%my_wm%blk_p,& - carrier%lastblk, carrier%datasize,& - carrier%m_sizes, carrier%n_sizes, carrier%k_sizes,& - carrier%c_local_rows, carrier%c_local_cols,& - carrier%c_has_symmetry, carrier%keep_sparsity, carrier%use_eps,& - carrier%param_sets,& - carrier%queue,& - ps_group%master%s%parameters, advance_memreg,& - carrier%m_size_maps, carrier%n_size_maps, carrier%k_size_maps,& - carrier%m_size_maps_size, carrier%n_size_maps_size, carrier%k_size_maps_size,& - carrier%nm_stacks, carrier%nn_stacks, carrier%nk_stacks, & - carrier%stack_map,& - nstacks, carrier%default_stack, & - carrier%row_max_epss, csr_a_norms, csr_b_norms,& - carrier%flop, error) - ! - ! If a stack group was filled up during the csr_multiply call then - ! we roll around to a new memory region. - IF (advance_memreg) THEN - CALL dbcsr_ps_set_advance (carrier%param_sets,& - advance_memreg = .TRUE.,& - error=error) - ! And make some progress in MPI - ithread = 0 -!$ ithread = omp_get_thread_num() - IF (use_comm_thread .AND. (ithread .EQ. 0)) & - CALL progress_comms(carrier) - END IF - ! - DEALLOCATE (a_row_p) - DEALLOCATE (b_row_p) - DEALLOCATE (a_blk_info) - DEALLOCATE (b_blk_info) - ENDIF - END SUBROUTINE csr_multiply_unwrap + CALL get_free_stack_column(csr_carrier, stackcol_data, stackcol_fillcount, error) + + + a_row_cycle: DO a_row_l = mi, mf + m_size = m_sizes(a_row_l) + + a_row_eps = row_max_epss (a_row_l) + mapped_row_size = row_size_maps(m_size) + + a_blk_cycle: DO a_blk = a_row_p(a_row_l)+1, a_row_p(a_row_l+1) + a_col_l = a_blk_info(1, a_blk) + IF (debug_mod) WRITE(*,*)ithread,routineN//" A col", a_col_l,";",a_row_l + k_size = k_sizes (a_col_l) + mapped_k_size = k_size_maps(k_size) + + a_norm = left_norms(a_blk) + b_blk_cycle: DO b_blk = b_row_p(a_col_l)+1, b_row_p(a_col_l+1) + IF (dbg) THEN + WRITE(*,'(1X,A,3(1X,I7),1X,A,1X,I16)')routineN//" trying B",& + a_row_l, b_blk_info(1,b_blk), a_col_l, "at", b_blk_info(2,b_blk) + ENDIF + b_norm = right_norms(b_blk) + IF (a_norm * b_norm .LT. a_row_eps) THEN + CYCLE + ENDIF + b_col_l = b_blk_info(1,b_blk) + ! Don't calculate symmetric blocks. + symmetric_product: IF (c_has_symmetry) THEN + c_row_logical = c_local_rows (a_row_l) + c_col_logical = c_local_cols (b_col_l) + IF (c_row_logical .NE. c_col_logical& + .AND. my_checker_tr (c_row_logical, c_col_logical)) THEN + IF (dbg) THEN + WRITE(*,*)"Skipping symmetric block!", c_row_logical,& + c_col_logical + ENDIF + CYCLE + ENDIF + ENDIF symmetric_product + + c_blk_id = hash_table_get (c_hashes(a_row_l), b_col_l) + IF (.FALSE.) THEN + WRITE(*,'(1X,A,3(1X,I7),1X,A,1X,I16)')routineN//" coor",& + a_row_l, a_col_l, b_col_l,"c blk", c_blk_id + ENDIF + block_exists = c_blk_id .GT. 0 + + n_size = n_sizes(b_col_l) + c_nze = m_size * n_size + ! + IF (block_exists) THEN + offset = c_blk_p(c_blk_id) + ELSE + IF (keep_sparsity) CYCLE + + offset = datasize + 1 + lastblk = lastblk+1 + datasize = datasize + c_nze + c_blk_id = lastblk ! assign a new c-block-id + + IF (dbg) WRITE(*,*)routineN//" new block offset, nze", offset, c_nze + CALL hash_table_add(c_hashes(a_row_l),& + b_col_l, c_blk_id, error=error) + + ! We still keep the linear index because it's + ! easier than getting the values out of the + ! hashtable in the end. + c_row_i(lastblk) = a_row_l + c_col_i(lastblk) = b_col_l + c_blk_p(lastblk) = offset + ENDIF + + ! TODO: this is only called withcareful_mod + ! We should not call certain MM routines (netlib BLAS) + ! with zero LDs; however, we still need to get to here + ! to get new blocks. + IF (careful_mod) THEN + IF (c_nze .EQ. 0 .OR. k_size .EQ. 0) THEN + CALL dbcsr_assert (.FALSE.,& + dbcsr_fatal_level, dbcsr_internal_error, routineN,& + "Can not call MM with LDx=0.", __LINE__, error=error) + CYCLE + ENDIF + ENDIF + + mapped_col_size = col_size_maps (n_size) + ws = stack_map (mapped_col_size, mapped_k_size, mapped_row_size) + stackcol_fillcount(ws) = stackcol_fillcount(ws) + 1 + s_dp = stackcol_fillcount(ws) + + stackcol_data(p_m, s_dp, ws) = m_size + stackcol_data(p_n, s_dp, ws) = n_size + stackcol_data(p_k, s_dp, ws) = k_size + stackcol_data(p_a_first, s_dp, ws) = a_blk_info(2, a_blk) + stackcol_data(p_b_first, s_dp, ws) = b_blk_info(2, b_blk) + stackcol_data(p_c_first, s_dp, ws) = offset + stackcol_data(p_c_blk, s_dp, ws) = c_blk_id + + flop = flop + INT(2*c_nze, int_8) * INT(k_size, int_8) + + flush_stack = stackcol_fillcount(ws) >= SIZE(stackcol_data, 2) + IF (flush_stack) & + CALL get_free_stack_column(csr_carrier, stackcol_data, stackcol_fillcount, error) + + ENDDO b_blk_cycle ! b + ENDDO a_blk_cycle ! a_col + ENDDO a_row_cycle ! a_row + + + END SUBROUTINE dbcsr_mm_csr_multiply_low ! ***************************************************************************** -!> \brief Call in MPI to progrss any outstanding communications -!> TODO: copied from dbcsr_internal_operations. MPI does not belong on this level. -! ***************************************************************************** - SUBROUTINE progress_comms(carrier) - TYPE(carrier_type), INTENT(inout) :: carrier - - CALL mp_testany(carrier%right_data_sr) - CALL mp_testany(carrier%right_data_rr) - CALL mp_testany(carrier%left_data_sr) - CALL mp_testany(carrier%left_data_rr) - CALL mp_testany(carrier%right_index_sr) - CALL mp_testany(carrier%right_index_rr) - CALL mp_testany(carrier%left_index_sr) - CALL mp_testany(carrier%left_index_rr) - END SUBROUTINE - - -! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_init +!> \brief Initializes a multiplication cycle for new set of C-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply_outer_init(left, right, product, carrier, fill_guess, error) + SUBROUTINE dbcsr_mm_csr_outer_init(csr_carrier, left, right, product, fill_guess,& + m_sizes, n_sizes, k_sizes, error) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier TYPE(dbcsr_type), INTENT(IN) :: left, right TYPE(dbcsr_type), INTENT(INOUT) :: product - TYPE(carrier_type), INTENT(INOUT) :: carrier REAL(KIND=real_8) :: fill_guess + INTEGER, DIMENSION(:), POINTER :: m_sizes, n_sizes, k_sizes TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'csr_multiply_outer_init', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_csr_outer_init', & routineP = moduleN//':'//routineN INTEGER :: block_estimate, default_stack, istack, ithread, k_map, k_size, & - m_map, m_size, mem_type, n_map, n_size, n_stack_buffers, & - n_stack_mem_regions, nstacks, nthreads, ps_buffer, ps_g, ps_memreg + m_map, m_size, n_map, n_size, n_stack_buffers, nstacks, nthreads, ps_g INTEGER, ALLOCATABLE, DIMENSION(:) :: flop_index, flop_list, & most_common_k, most_common_m, & most_common_n INTEGER, DIMENSION(3) :: nxstacks - LOGICAL :: local_cols, local_indexing, & - local_rows - TYPE(dbcsr_ps_group_type), POINTER :: ps_group - TYPE(dbcsr_ps_target_obj) :: product_target + LOGICAL :: local_indexing + TYPE(stack_descriptor_type), & + ALLOCATABLE, DIMENSION(:) :: tmp_descr ithread = 0 ; nthreads = 1 - !$ ithread = OMP_GET_THREAD_NUM () ; nthreads = OMP_GET_NUM_THREADS () - + !$ ithread = OMP_GET_THREAD_NUM () ; nthreads = OMP_GET_NUM_THREADS () + ! find out if we have local_indexing - local_cols = right%local_indexing - local_rows = left%local_indexing - CALL dbcsr_assert (local_cols, "EQV", local_rows,& + CALL dbcsr_assert (right%local_indexing, "EQV", left%local_indexing,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Local index useage must be consistent.", __LINE__, error=error) - local_indexing = local_rows - - + local_indexing = left%local_indexing + ! Setup the hash tables if needed - IF (local_indexing) THEN - ALLOCATE (carrier%c_hashes (product%nblkrows_local)) - ELSE - ALLOCATE (carrier%c_hashes (product%nblkrows_total)) - ENDIF block_estimate=MAX(product%nblks,left%nblks,right%nblks)/nthreads IF (local_indexing) THEN - CALL fill_hash_tables (carrier%c_hashes, product,block_estimate,& + ALLOCATE (csr_carrier%c_hashes (product%nblkrows_local)) + CALL fill_hash_tables (csr_carrier%c_hashes, product,block_estimate,& row_map=array_data(product%global_rows),& col_map=array_data(product%global_cols),& error=error) ELSE - CALL fill_hash_tables (carrier%c_hashes, product,block_estimate,& + ALLOCATE (csr_carrier%c_hashes (product%nblkrows_total)) + CALL fill_hash_tables (csr_carrier%c_hashes, product,block_estimate,& error=error) ENDIF - ! + ! Setup the MM stack - CALL dbcsr_get_conf_nstacks (nxstacks, n_stack_buffers, n_stack_mem_regions,& - error) - carrier%nm_stacks = nxstacks(1) - carrier%nn_stacks = nxstacks(2) - carrier%nk_stacks = nxstacks(3) + CALL dbcsr_get_conf_nstacks (nxstacks, n_stack_buffers, error) + csr_carrier%nm_stacks = nxstacks(1) + csr_carrier%nn_stacks = nxstacks(2) + csr_carrier%nk_stacks = nxstacks(3) nstacks = nxstacks(1) * nxstacks(2) * nxstacks(3) + 1 - CALL dbcsr_assert (nstacks, "LE", INT (HUGE (carrier%stack_map)),& + CALL dbcsr_assert (nstacks, "LE", INT (HUGE (csr_carrier%stack_map)),& dbcsr_fatal_level, dbcsr_internal_error, routineN,& "Too many stacks requested (global/dbcsr/n_size_*_stacks in input)",& __LINE__, error=error) - ! - CALL dbcsr_ps_target_new (product_target, error) - CALL dbcsr_ps_target_add_data (product_target%t,& - product%wms(ithread+1)%data_area, carrier%datasize, error=error) - - IF (mm_driver .EQ. mm_driver_cuda) THEN - mem_type = dbcsr_memory_CUDA_host_pinned - ELSE - mem_type = dbcsr_memory_default - ENDIF - - ! Here the first driver init part used to be - - CALL dbcsr_ps_set_create (carrier%param_sets, mm_stack_size,& - product_target, nstacks, n_stack_buffers, n_stack_mem_regions,& - mem_type,error=error) - - !moved this to the end as product_target is need for driver_init - !CALL dbcsr_ps_target_release (product_target, error) - - ! Setup the block sizes mappings. The carrier%*_sizes arrays are - ! mappings from block sizes to an index from the number of most - ! common block sizes. I.e., if nxstacks(1) = 2 and the most - ! common blocks sizes are 13 and 5, then the values in - ! carrier%m_sizes will be 3 for all elements except 13 and 5; - ! these two elemnts will be either 1 or 2. - ! + + + ALLOCATE(csr_carrier%stackrow_descr(nstacks)) + + DO istack=1, nstacks + csr_carrier%stackrow_descr(istack)%total_entries = 0 + END DO + ALLOCATE (most_common_m(nxstacks(1))) ALLOCATE (most_common_n(nxstacks(2))) ALLOCATE (most_common_k(nxstacks(3))) - CALL map_most_common (carrier%m_sizes, carrier%m_size_maps, nxstacks(1),& + CALL map_most_common (m_sizes, csr_carrier%m_size_maps, nxstacks(1),& most_common_m,& - max_stack_block_size, carrier%max_m) - carrier%m_size_maps_size = SIZE (carrier%m_size_maps) - CALL map_most_common (carrier%n_sizes, carrier%n_size_maps, nxstacks(2),& + max_stack_block_size, csr_carrier%max_m) + csr_carrier%m_size_maps_size = SIZE (csr_carrier%m_size_maps) + CALL map_most_common (n_sizes, csr_carrier%n_size_maps, nxstacks(2),& most_common_n,& - max_stack_block_size, carrier%max_n) - carrier%n_size_maps_size = SIZE (carrier%n_size_maps) + max_stack_block_size, csr_carrier%max_n) + csr_carrier%n_size_maps_size = SIZE (csr_carrier%n_size_maps) CALL map_most_common (array_data(right%row_blk_size),& - carrier%k_size_maps, nxstacks(3), & + csr_carrier%k_size_maps, nxstacks(3), & most_common_k,& - max_stack_block_size, carrier%max_k) - carrier%k_size_maps_size = SIZE (carrier%k_size_maps) - ! + max_stack_block_size, csr_carrier%max_k) + csr_carrier%k_size_maps_size = SIZE (csr_carrier%k_size_maps) + ! Creates the stack map--a mapping from (mapped) stack block sizes ! (carrier%*_sizes) to a stack number. Triples with even one ! uncommon size will be mapped to a general, non-size-specific ! stack. - ALLOCATE (carrier%stack_map(nxstacks(2)+1, nxstacks(3)+1, nxstacks(1)+1)) + ALLOCATE (csr_carrier%stack_map(nxstacks(2)+1, nxstacks(3)+1, nxstacks(1)+1)) default_stack = nstacks - carrier%default_stack = default_stack + DO m_map = 1, nxstacks(1)+1 IF (m_map .LE. nxstacks(1)) THEN m_size = most_common_m(m_map) @@ -374,48 +499,30 @@ MODULE dbcsr_mm_csr .AND. n_map .LE. nxstacks(2)) THEN ! This is the case when m, n, and k are all defined. ps_g = (m_map-1)*nxstacks(2)*nxstacks(3) +& - (k_map-1)*nxstacks(2) +& - n_map + (k_map-1)*nxstacks(2) + n_map ps_g = nstacks-ps_g - carrier%stack_map(n_map, k_map, m_map) = ps_g + csr_carrier%stack_map(n_map, k_map, m_map) = ps_g ! Also take care of the stack m, n, k descriptors - DO ps_memreg = 1, n_stack_mem_regions - DO ps_buffer = 1, n_stack_buffers - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - ps_group%stacks(ps_g)%s%m = m_size - ps_group%stacks(ps_g)%s%n = n_size - ps_group%stacks(ps_g)%s%k = k_size - ps_group%stacks(ps_g)%s%max_m = m_size - ps_group%stacks(ps_g)%s%max_n = n_size - ps_group%stacks(ps_g)%s%max_k = k_size - ps_group%stacks(ps_g)%s%defined_mnk = .TRUE. - ! The bins are quasi-sorted according from those - ! with largest sizes (best for accelerators) to - ! those with smallest (worst for accelerators). - ps_group%stacks(ps_g)%s%size_bin = ps_g - ENDDO - ENDDO + csr_carrier%stackrow_descr(ps_g)%m = m_size + csr_carrier%stackrow_descr(ps_g)%n = n_size + csr_carrier%stackrow_descr(ps_g)%k = k_size + csr_carrier%stackrow_descr(ps_g)%max_m = m_size + csr_carrier%stackrow_descr(ps_g)%max_n = n_size + csr_carrier%stackrow_descr(ps_g)%max_k = k_size + csr_carrier%stackrow_descr(ps_g)%defined_mnk = .TRUE. ELSE ! This is the case when at least one of m, n, or k is ! undefined. ps_g = default_stack - carrier%stack_map(n_map, k_map, m_map) = default_stack + csr_carrier%stack_map(n_map, k_map, m_map) = default_stack ! Also take care of the stack m, n, k descriptors - DO ps_memreg = 1, n_stack_mem_regions - DO ps_buffer = 1, n_stack_buffers - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - ps_group%stacks(ps_g)%s%m = 0 - ps_group%stacks(ps_g)%s%n = 0 - ps_group%stacks(ps_g)%s%k = 0 - ps_group%stacks(ps_g)%s%max_m = carrier%max_m - ps_group%stacks(ps_g)%s%max_n = carrier%max_n - ps_group%stacks(ps_g)%s%max_k = carrier%max_k - ps_group%stacks(ps_g)%s%defined_mnk = .FALSE. - ps_group%stacks(ps_g)%s%size_bin = default_stack - ENDDO - ENDDO + csr_carrier%stackrow_descr(ps_g)%m = 0 + csr_carrier%stackrow_descr(ps_g)%n = 0 + csr_carrier%stackrow_descr(ps_g)%k = 0 + csr_carrier%stackrow_descr(ps_g)%max_m = csr_carrier%max_m + csr_carrier%stackrow_descr(ps_g)%max_n = csr_carrier%max_n + csr_carrier%stackrow_descr(ps_g)%max_k = csr_carrier%max_k + csr_carrier%stackrow_descr(ps_g)%defined_mnk = .FALSE. END IF ENDDO ENDDO @@ -427,35 +534,58 @@ MODULE dbcsr_mm_csr ! sort to make the order fixed... all defined stacks first, default stack ! last. Next, sort according to flops, first stack lots of flops, last ! stack, few flops - IF (nstacks>1) THEN - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets, 1, 1, error=error) - ALLOCATE(flop_list(nstacks-1),flop_index(nstacks-1)) - DO istack=1,nstacks-1 - flop_list(istack)=-2*ps_group%stacks(istack)%s%m*ps_group%stacks(istack)%s%n*ps_group%stacks(istack)%s%k - ENDDO - CALL sort(flop_list,nstacks-1,flop_index) - DO ps_memreg = 1, n_stack_mem_regions - DO ps_buffer = 1, n_stack_buffers - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - DO istack=1,nstacks-1 - ps_group%stacks(istack)%s%size_bin = flop_index(istack) - ENDDO - ENDDO - ENDDO - DEALLOCATE(flop_list,flop_index) - ENDIF + ! The default stack shall remain at the end of the gridcolumn + ALLOCATE(flop_list(nstacks-1),flop_index(nstacks-1), tmp_descr(nstacks)) + DO istack=1,nstacks-1 + flop_list(istack) = -2 * csr_carrier%stackrow_descr(istack)%m& + * csr_carrier%stackrow_descr(istack)%n& + * csr_carrier%stackrow_descr(istack)%k + ENDDO + + CALL sort(flop_list, nstacks-1, flop_index) + tmp_descr = csr_carrier%stackrow_descr + DO istack=1,nstacks-1 + csr_carrier%stackrow_descr(istack) = tmp_descr(flop_index(istack)) + ENDDO + + DO m_map = 1, SIZE(csr_carrier%stack_map, 1) + DO k_map = 1, SIZE(csr_carrier%stack_map, 2) + map_loop: DO n_map = 1, SIZE(csr_carrier%stack_map, 1) + DO istack=1,nstacks-1 + IF(csr_carrier%stack_map(m_map, k_map, n_map) == flop_index(istack)) THEN + csr_carrier%stack_map(m_map, k_map, n_map) = istack + CYCLE map_loop + END IF + ENDDO + ENDDO map_loop + ENDDO + ENDDO + DEALLOCATE(flop_list,flop_index,tmp_descr) + + + + + ! Driver allocates stackgrid_data and stackgrid_state, if needed as host-pinned. + NULLIFY(csr_carrier%stackgrid_data, csr_carrier%stackgrid_state) + CALL dbcsr_mm_driver_outer_init(left=left, right=right, product=product,& + drv_carrier=csr_carrier%drv_carrier, fill_guess=fill_guess,& + stackgrid_data=csr_carrier%stackgrid_data, & + stackgrid_state=csr_carrier%stackgrid_state, & + nstacks=nstacks, n_stack_buffers=n_stack_buffers, error=error) + + IF(.NOT. ASSOCIATED(csr_carrier%stackgrid_data)) & + STOP "dbcsr_mm_csr_outer_init: stackgrid_data not associated" + + IF(.NOT. ASSOCIATED(csr_carrier%stackgrid_state)) & + STOP "dbcsr_mm_csr_outer_init: stackgrid_state not associated" + + ALLOCATE(csr_carrier%stackgrid_fillcount(nstacks, n_stack_buffers)) + csr_carrier%stackgrid_fillcount = 0 + csr_carrier%stackgrid_state = dbcsr_ps_state_empty + + + END SUBROUTINE dbcsr_mm_csr_outer_init - CALL dbcsr_mm_driver_outer_init(left, right, product, product_target, carrier, fill_guess, error=error) - - CALL dbcsr_ps_target_release (product_target, error) - - ALLOCATE (carrier%queue) - CALL dbcsr_pq_create (carrier%queue, nstacks, error) - CALL dbcsr_pq_share (carrier%queue, error) - ! - END SUBROUTINE csr_multiply_outer_init - ! ***************************************************************************** !> \brief Fills row hashtable from an existing matrix. @@ -509,435 +639,241 @@ MODULE dbcsr_mm_csr CALL dbcsr_error_stop(error_handler, error) END SUBROUTINE fill_hash_tables - + ! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_finalize +!> \brief Finalizes a multiplication cycle for a set of C-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply_outer_finalize(carrier, product, error) - TYPE(carrier_type), INTENT(INOUT) :: carrier + SUBROUTINE dbcsr_mm_csr_outer_finalize(csr_carrier, product, error) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier TYPE(dbcsr_type), INTENT(inout) :: product TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'csr_multiply_outer_finalize', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_csr_outer_finalize', & routineP = moduleN//':'//routineN INTEGER :: i - CALL dbcsr_mm_driver_outer_finalize(carrier, product, error) - -! Clear hash tables - DO i = 1, SIZE(carrier%c_hashes) - CALL hash_table_release (carrier%c_hashes (i)) +! The driver deallocates stackgrid_data and stackgrid_state as it might be host-pinned. + + CALL dbcsr_mm_driver_outer_finalize(drv_carrier=csr_carrier%drv_carrier,& + product=product, stackgrid_data=csr_carrier%stackgrid_data,& + stackgrid_state=csr_carrier%stackgrid_state,& + error=error) + + IF(ASSOCIATED(csr_carrier%stackgrid_data)) & + STOP "dbcsr_mm_csr_outer_finalize: stackgrid_data still associated" + IF(ASSOCIATED(csr_carrier%stackgrid_state)) & + STOP "dbcsr_mm_csr_outer_finalize: stackgrid_state still associated" + + ! Clear hash tables + DO i = 1, SIZE(csr_carrier%c_hashes) + CALL hash_table_release (csr_carrier%c_hashes(i)) ENDDO - DEALLOCATE (carrier%c_hashes) - + DEALLOCATE (csr_carrier%c_hashes) - - ! Clear MM stack - !CALL dbcsr_psg_rm_data_c (& - ! dbcsr_ps_set_get_group(carrier%param_sets, 1, 1, error), error=error) + DEALLOCATE(csr_carrier%stackrow_descr) + DEALLOCATE(csr_carrier%stackgrid_fillcount) + DEALLOCATE(csr_carrier%stack_map) + DEALLOCATE(csr_carrier%m_size_maps) + DEALLOCATE(csr_carrier%n_size_maps) + DEALLOCATE(csr_carrier%k_size_maps) + + END SUBROUTINE dbcsr_mm_csr_outer_finalize - ! maybe a call to dbcsr_psg_rm_data_ab in a critical section would be enough - !$OMP CRITICAL (crit_data) - CALL dbcsr_ps_set_destroy (carrier%param_sets, error=error) - !$OMP END CRITICAL (crit_data) - - - CALL dbcsr_pq_unshare (carrier%queue, error) - CALL dbcsr_pq_destroy (carrier%queue, error) - DEALLOCATE (carrier%queue) - - END SUBROUTINE csr_multiply_outer_finalize ! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_sparse +!> \brief Initializes a multiplication cycle for a new set of A- and B-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply_inner_init(left, right, carrier, error) + SUBROUTINE dbcsr_mm_csr_inner_init(left, right, csr_carrier, error) TYPE(dbcsr_type), INTENT(IN) :: left, right - TYPE(carrier_type), INTENT(INOUT) :: carrier + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier TYPE(dbcsr_error_type), INTENT(INOUT) :: error - INTEGER :: ps_buffer, ps_memreg - TYPE(dbcsr_ps_group_type), POINTER :: stack_group + CALL dbcsr_mm_driver_inner_init(left, right, csr_carrier%drv_carrier, error) + END SUBROUTINE dbcsr_mm_csr_inner_init - !$OMP BARRIER - -! Setup the carrier data that changes in each multiplication step. - - DO ps_memreg = 1, carrier%param_sets%nmemregs - DO ps_buffer = 1, carrier%param_sets%nbuffers - stack_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - !$OMP CRITICAL (crit_data) - CALL dbcsr_psg_add_data_ab (stack_group,& - left%data_area, right%data_area, error=error) - !$OMP END CRITICAL (crit_data) - ENDDO - ENDDO - ! - ! Quick reset of the queue to avoid heavyweight de/allocations. - CALL dbcsr_pq_refresh (carrier%queue,& - flush_level=(carrier%param_sets%nbuffers*carrier%param_sets%group_size),& - error=error) - - CALL dbcsr_mm_driver_inner_init(left, right, carrier, error) - !$OMP BARRIER - - END SUBROUTINE csr_multiply_inner_init - ! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_sparse +!> \brief Finalizes a multiplication cycle for a set of A- and B-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply_inner_finalize(carrier, error) - TYPE(carrier_type), INTENT(INOUT) :: carrier + SUBROUTINE dbcsr_mm_csr_inner_finalize(csr_carrier, error) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier TYPE(dbcsr_error_type), INTENT(INOUT) :: error - INTEGER :: ps_buffer, ps_memreg - LOGICAL :: i_interface - TYPE(dbcsr_ps_group_type), POINTER :: stack_group +! submit all left over stacks -! Mark myself as done with indexing. + CALL process_stacks(csr_carrier, driver=mm_driver, min_fill=0, error=error) + CALL dbcsr_mm_driver_inner_finalize(csr_carrier%drv_carrier, error=error) + END SUBROUTINE dbcsr_mm_csr_inner_finalize - CALL dbcsr_pq_mark_done (carrier%queue, error) - i_interface = .FALSE. - IF (mm_thread_workshare) THEN - !$OMP MASTER - ! - ! I am the thread that interfaces to the accelerator. - i_interface = mm_async - !$OMP END MASTER - ELSE - i_interface = mm_async - ENDIF - ! - ! Queue all outstanding stacks. - DO ps_memreg = 1, carrier%param_sets%nmemregs - DO ps_buffer = 1, carrier%param_sets%nbuffers - stack_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - wait=.FALSE., error=error) - ! Only enqueue the stack group if it is not already queued - ! or being processed. - IF (dbcsr_psg_get_state (stack_group, error) & - .LT. dbcsr_ps_state_queued) THEN - CALL enqueue_ps_group (carrier%queue,& - stack_group, error) - ENDIF - ENDDO - ENDDO - ! - ! Process my queues now. - IF (.NOT. i_interface) THEN - ! Non-master threads just do CPU calculations. - CALL process_queue_mine(carrier%queue, driver=mm_host_driver,& - error=error) - ELSE - ! The master thread tries to fill up the accelerator. - CALL process_queue_mine (carrier%queue, driver=mm_driver,& - error=error) - - IF (mm_thread_workshare) THEN - CALL process_queue_others (carrier%queue, forever=.FALSE.,& - driver=mm_driver, error=error) - ENDIF - - CALL process_queue_mine (carrier%queue,& - driver=mm_host_driver, error=error) - - IF (mm_thread_workshare) THEN - CALL process_queue_others (carrier%queue, forever=.TRUE.,& - driver=mm_driver, error=error) - ENDIF - ENDIF - - IF (mm_thread_workshare) THEN - !$OMP BARRIER - ENDIF - - !TODO: why is this only called on one stack_group see also csr_multiply_init - ! - !$OMP CRITICAL (crit_data) - CALL dbcsr_psg_rm_data_ab (stack_group, error=error) - !$OMP END CRITICAL (crit_data) - - END SUBROUTINE csr_multiply_inner_finalize - ! ***************************************************************************** -!> \brief Performs multiplication of smaller submatrices. -!> \note The queue parameter could be INTENT(INOUT) when OpenMP is not used. +!> \brief Processes stacks in the stackgrid which have min_fill or more entries. +!> \param driver Which driver (smm, blas, cuda,...) should be used +!> \param min_fill Only process stacks that contain at least min_fill items. +!> \param max_stacks Process only given number of stacks. Not present = no limit. +!> \param start_below If set, the stackgrid will be search bottom-up. +!> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE csr_multiply(mi, mf, ni, nf, ki, kf,& - ai, af, a_row_p, a_blk_info, bi, bf, b_row_p, b_blk_info,& - c_hashes, c_row_i, c_col_i, c_blk_p, lastblk, datasize,& - m_sizes, n_sizes, k_sizes,& - c_local_rows, c_local_cols,& - c_has_symmetry, keep_sparsity, use_eps,& - param_sets, queue,& - params_array, advance_memreg, & - row_size_maps, col_size_maps, k_size_maps,& - row_size_maps_size, col_size_maps_size, k_size_maps_size,& - nm_stacks, nn_stacks, nk_stacks, stack_map,& - nstacks, default_stack,& - row_max_epss, left_norms, right_norms,& - flop, error) - INTEGER, INTENT(IN) :: mi, mf, ni, nf, ki, kf, ai, af - INTEGER, DIMENSION(mi:mf+1), INTENT(IN) :: a_row_p - INTEGER, DIMENSION(2, 1:af-ai+1), & - INTENT(IN) :: a_blk_info - INTEGER, INTENT(IN) :: bi, bf - INTEGER, DIMENSION(ki:kf+1), INTENT(IN) :: b_row_p - INTEGER, DIMENSION(2, 1:bf-bi+1), & - INTENT(IN) :: b_blk_info - TYPE(hash_table_type), DIMENSION(:), & - INTENT(INOUT) :: c_hashes - INTEGER, DIMENSION(*), INTENT(INOUT) :: c_row_i, c_col_i, c_blk_p - INTEGER, INTENT(INOUT) :: lastblk, datasize - INTEGER, DIMENSION(*), INTENT(IN) :: m_sizes, n_sizes, k_sizes, & - c_local_rows, c_local_cols - LOGICAL, INTENT(IN) :: c_has_symmetry, & - keep_sparsity, use_eps - TYPE(dbcsr_ps_set_type), INTENT(INOUT) :: param_sets - TYPE(dbcsr_pq_type), POINTER :: queue - INTEGER, DIMENSION(*), INTENT(INOUT) :: params_array - LOGICAL, INTENT(OUT) :: advance_memreg - INTEGER, INTENT(IN) :: row_size_maps_size, & - k_size_maps_size, & - col_size_maps_size - INTEGER(KIND=int_4), & - DIMENSION(0:row_size_maps_size-1), & - INTENT(IN) :: row_size_maps - INTEGER(KIND=int_4), & - DIMENSION(0:col_size_maps_size-1), & - INTENT(IN) :: col_size_maps - INTEGER(KIND=int_4), & - DIMENSION(0:k_size_maps_size-1), & - INTENT(IN) :: k_size_maps - INTEGER, INTENT(IN) :: nm_stacks, nn_stacks, & - nk_stacks - INTEGER(KIND=int_1), DIMENSION(& - nn_stacks+1, nk_stacks+1, nm_stacks+1)& - , INTENT(IN) :: stack_map - INTEGER, INTENT(IN) :: nstacks, default_stack - REAL(kind=sp), DIMENSION(*) :: row_max_epss, left_norms, & - right_norms - INTEGER(KIND=int_8), INTENT(INOUT) :: flop +SUBROUTINE process_stacks(csr_carrier, driver, min_fill, max_stacks, start_below, error) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier + INTEGER, INTENT(IN) :: driver, min_fill + INTEGER, INTENT(IN), OPTIONAL :: max_stacks + LOGICAL, INTENT(IN), OPTIONAL :: start_below TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'csr_multiply', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: dbg = .FALSE., & - local_timing = .FALSE. + INTEGER :: i, j, n_stack_buffers, & + nstacks, num_processed + INTEGER, DIMENSION(:, :), POINTER :: stack_data + INTEGER, POINTER :: stack_fillcount, stack_state + TYPE(stack_descriptor_type), POINTER :: stack_descr - INTEGER :: a_blk, a_col_l, a_row_l, b_blk, b_col_l, c, c_blk_id, & - c_blk_pt, c_col_logical, c_nze, c_row_logical, ithread, k_size, m_size, & - mapped_col_size, mapped_k_size, mapped_row_size, n_size, new_blk, & - nworking, s_dp, ws, zero_first, zero_last - INTEGER, DIMENSION(nstacks) :: param_starts, stack_p - INTEGER, DIMENSION(:), POINTER :: params_array_direct - INTEGER(KIND=int_4) :: offset - LOGICAL :: block_exists, do_preempt, & - flush_stack, i_interface - REAL(kind=sp) :: a_norm, a_row_eps, b_norm - TYPE(dbcsr_ps_group_type), POINTER :: ps_group + INTEGER ::j_start, j_end, j_incr -! --------------------------------------------------------------------------- + num_processed = 0 + nstacks = SIZE(csr_carrier%stackgrid_data, 3) + n_stack_buffers = SIZE(csr_carrier%stackgrid_data, 4) - ithread = 0 - !$ ithread = omp_get_thread_num() - ! - advance_memreg = .FALSE. - i_interface = .FALSE. - IF (mm_thread_workshare) THEN - !$OMP MASTER - ! I am the thread that interfaces to the accelerator. - i_interface = mm_async - !$OMP END MASTER - ELSE - i_interface = mm_async + j_start=1; j_end=nstacks; j_incr=1 + IF(PRESENT(start_below)) THEN + IF(start_below) THEN + j_start=nstacks; j_end=1; j_incr=-1 + ENDIF ENDIF - ! - ! Each thread always shares the same zero_first, zero_last, and - ! new_blk. All of the parameter stacks should have the same - ! value. - ps_group => dbcsr_ps_set_get_group_p (param_sets, error=error) - CALL dbcsr_psg_view_open (ps_group, params_array_direct, stack_p,& - zero_first, zero_last, new_blk, param_starts, error=error) - ! - ! New data blocks will be put into the data area starting at - ! the c_blk_pt position. - new_blk = lastblk - c_blk_pt = datasize + 1 - ws = 1 - ! - a_row_cycle: DO a_row_l = mi, mf - m_size = m_sizes(a_row_l) - a_row_eps = row_max_epss (a_row_l) - mapped_row_size = row_size_maps(m_size) + DO i=1, n_stack_buffers + DO j=j_start, j_end, j_incr + IF(csr_carrier%stackgrid_fillcount(j,i) > min_fill) THEN + stack_data=>csr_carrier%stackgrid_data(:,:,j,i) + stack_fillcount=>csr_carrier%stackgrid_fillcount(j,i) + stack_state=>csr_carrier%stackgrid_state(j,i) + stack_descr=>csr_carrier%stackrow_descr(j) - a_blk_cycle: DO a_blk = a_row_p(a_row_l)+1, a_row_p(a_row_l+1) - a_col_l = a_blk_info(1, a_blk) - IF (debug_mod) WRITE(*,*)ithread,routineN//" A col", a_col_l,";",a_row_l - k_size = k_sizes (a_col_l) - mapped_k_size = k_size_maps(k_size) + CALL dbcsr_mm_driver_process_stack(& + drv_carrier=csr_carrier%drv_carrier,& + driver=driver,& + stack_data=stack_data,& + stack_fillcount=stack_fillcount,& + stack_state=stack_state,& + stack_descr=stack_descr,& + stack_id=j + (i-1)*nstacks,& + error=error) - a_norm = left_norms(a_blk) - b_blk_cycle: DO b_blk = b_row_p(a_col_l)+1, b_row_p(a_col_l+1) - IF (dbg) THEN - WRITE(*,'(1X,A,3(1X,I7),1X,A,1X,I16)')routineN//" trying B",& - a_row_l, b_blk_info(1,b_blk), a_col_l, "at", b_blk_info(2,b_blk) - ENDIF - b_norm = right_norms(b_blk) - IF (a_norm * b_norm .LT. a_row_eps) THEN - CYCLE - ENDIF - b_col_l = b_blk_info(1,b_blk) - ! Don't calculate symmetric blocks. - symmetric_product: IF (c_has_symmetry) THEN - c_row_logical = c_local_rows (a_row_l) - c_col_logical = c_local_cols (b_col_l) - IF (c_row_logical .NE. c_col_logical& - .AND. my_checker_tr (c_row_logical, c_col_logical)) THEN - IF (dbg) THEN - WRITE(*,*)"Skipping symmetric block!", c_row_logical,& - c_col_logical - ENDIF - CYCLE - ENDIF - ENDIF symmetric_product + num_processed = num_processed + 1 + IF(PRESENT(max_stacks)) THEN + IF(num_processed >= max_stacks) RETURN + END IF + END IF + END DO + END DO - c_blk_id = hash_table_get (c_hashes(a_row_l), b_col_l) - IF (.FALSE.) THEN - WRITE(*,'(1X,A,3(1X,I7),1X,A,1X,I16)')routineN//" coor",& - a_row_l, a_col_l, b_col_l,"c blk", c_blk_id - ENDIF - block_exists = c_blk_id .GT. 0 +END SUBROUTINE process_stacks - n_size = n_sizes(b_col_l) - c_nze = m_size * n_size - ! - new_block_case: IF (.NOT. block_exists) THEN - sparsity_enforcement: IF (keep_sparsity) THEN - CYCLE - ENDIF sparsity_enforcement - offset = c_blk_pt - new_blk = new_blk+1 - c_blk_id = new_blk - IF (dbg) WRITE(*,*)routineN//" new block offset, nze", offset, c_nze - CALL hash_table_add(c_hashes(a_row_l),& - b_col_l, c_blk_id, error=error) - ! - ! We still keep the linear index because it's - ! easier than getting the values out of the - ! hashtable in the end. - c_row_i(new_blk) = a_row_l - c_col_i(new_blk) = b_col_l - c_blk_p(new_blk) = offset - ! - c_blk_pt = c_blk_pt + c_nze - datasize = datasize + c_nze - zero_last = c_blk_pt - 1 - ELSE - offset = c_blk_p(c_blk_id) - ENDIF new_block_case - ! - ! We should not call certain MM routines (netlib BLAS) - ! with zero LDs; however, we still need to get to here - ! to get new blocks. - IF (careful_mod) THEN - IF (c_nze .EQ. 0 .OR. k_size .EQ. 0) THEN - CALL dbcsr_assert (.FALSE.,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "Can not call MM with LDx=0.", __LINE__, error=error) - CYCLE - ENDIF - ENDIF - ! - mapped_col_size = col_size_maps (n_size) - ws = stack_map (mapped_col_size, mapped_k_size, mapped_row_size) - s_dp = (param_starts(ws)-1 + stack_p(ws)) * dbcsr_ps_width - stack_p(ws) = stack_p(ws) + 1 - ! - params_array(s_dp+p_m) = m_size - params_array(s_dp+p_n) = n_size - params_array(s_dp+p_k) = k_size - ! - params_array(s_dp+p_a_first) = a_blk_info(2, a_blk) - ! - params_array(s_dp+p_b_first) = b_blk_info(2, b_blk) - ! - params_array(s_dp+p_c_first) = offset - params_array(s_dp+p_c_blk) = c_blk_id - ! - flop = flop + INT(2*c_nze, int_8) * INT(k_size, int_8) - ! - flush_stack = (stack_p(ws) .GE. mm_stack_size-1) - IF (flush_stack) THEN - advance_memreg = .TRUE. - CALL dbcsr_psg_view_close (ps_group, params_array_direct,& - stack_p, zero_first, zero_last, new_blk, error=error) - do_preempt = mm_async - IF (mm_async) THEN - nworking = dbcsr_ps_set_get_n_working (param_sets, error) - queue%nworking = nworking - IF (nworking .EQ. 0) THEN - !> If no stack in currently being processed then it - !> is assumed the accelerator can handle the stacks - !> on its own. The queue's flush_level is thus - !> increased, making it less favorable for the host - !> CPU to process stacks from the queue. - !> \see process_queue_preempt - !> \see get_stack_or_process_queue - CALL dbcsr_pq_flush_level_chg (queue,& - MAX(1,param_sets%nbuffers/1), param_sets) - CALL dbcsr_pq_handoff_level_chg (queue,& - MAX(1,param_sets%group_size/2), param_sets) - do_preempt = .FALSE. - ENDIF - ENDIF - CALL enqueue_ps_group (queue, ps_group, error=error) - ! - IF (i_interface) THEN - CALL process_queue_mine (queue, & - driver=mm_driver, error=error) - IF (mm_thread_workshare) THEN - CALL process_queue_others (queue, forever=.FALSE.,& - driver=mm_driver, error=error) - ENDIF - ENDIF - IF (do_preempt) THEN - ! Do some CPU stack calculations when needed. - CALL process_queue_preempt (queue, param_sets,& - driver=mm_host_driver, error=error) - ENDIF - ! - CALL dbcsr_ps_set_advance (param_sets,& - advance_memreg = .FALSE.,& - error=error) - ! - CALL get_stack_or_process_queue (param_sets,& - queue, ps_group, driver=mm_host_driver, error=error) - ! - CALL dbcsr_psg_view_open (ps_group, params_array_direct,& - stack_p, zero_first, zero_last, new_blk,& - param_starts, error=error) - ENDIF - ENDDO b_blk_cycle ! b - ENDDO a_blk_cycle ! a_col - ENDDO a_row_cycle ! a_row - ! - lastblk = new_blk - datasize = c_blk_pt -1 - ! - CALL dbcsr_psg_view_close (ps_group, params_array_direct,& - stack_p, zero_first, zero_last, new_blk, error=error) - - END SUBROUTINE csr_multiply +! ***************************************************************************** +!> \brief Returns a free column of the stackgrid. +!> If also processes some of the stacks in the stackgrid. +!> \author Ole Schuett +! ***************************************************************************** +SUBROUTINE get_free_stack_column(csr_carrier, stackcol_data, stackcol_fillcount, error) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier + INTEGER, DIMENSION(:, :, :), POINTER :: stackcol_data + INTEGER, DIMENSION(:), POINTER :: stackcol_fillcount + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + INTEGER :: i, j, mm_stack_size, & + n_stack_buffers, nstacks + + n_stack_buffers = SIZE(csr_carrier%stackgrid_data, 4) + nstacks = SIZE(csr_carrier%stackgrid_data, 3) + mm_stack_size = SIZE(csr_carrier%stackgrid_data, 2) + + CALL process_stacks(csr_carrier, driver=mm_driver, min_fill=mm_stack_size/2, error=error) + + ! checking for unkown stack states + DO i=1, n_stack_buffers + DO j=1, nstacks + IF((csr_carrier%stackgrid_state(j,i) /= dbcsr_ps_state_empty) & + .AND. (csr_carrier%stackgrid_state(j,i) /= dbcsr_ps_state_working)) THEN + WRITE (*,*) "odd stack state: ", csr_carrier%stackgrid_state(j,i) + STOP + END IF + END DO + END DO + + ! looking for a free stackgrid column + outer_loop: DO WHILE(.TRUE.) + DO i=1, n_stack_buffers + IF(ALL(csr_carrier%stackgrid_state(:,i) == dbcsr_ps_state_empty)) THEN + stackcol_data => csr_carrier%stackgrid_data(:,:,:,i) + stackcol_fillcount => csr_carrier%stackgrid_fillcount(:,i) + EXIT outer_loop + END IF + END DO + + ! Waiting for free stackgrid column, doing some cpu work in the meanwhile. + CALL process_stacks(csr_carrier, driver=mm_host_driver, & + min_fill=0, max_stacks=1, start_below=.TRUE., error=error) + END DO outer_loop + + + END SUBROUTINE get_free_stack_column + + +! ***************************************************************************** +!> \brief Prints a nice tabular summary of the stackgrid's current state. +!> \author Ole Schuett +! ***************************************************************************** +SUBROUTINE print_stackgrid(csr_carrier) + TYPE(csr_carrier_type), INTENT(INOUT) :: csr_carrier + + INTEGER :: i, j, n_stack_buffers, nstacks + + n_stack_buffers = SIZE(csr_carrier%stackgrid_data, 4) + nstacks = SIZE(csr_carrier%stackgrid_data, 3) + + ! print table header + WRITE(*,"(14X,A)",advance='no') "| total " + DO i=1, n_stack_buffers + WRITE(*,"(A,I3,A)",advance='no') "|", i, ". grp " + END DO + WRITE(*,"(A)",advance='yes') "|" + + ! print separation line below table header + WRITE(*,"(A)",advance='no') "--------------+-----------+" + DO j=1, n_stack_buffers + WRITE(*,"(A)",advance='no') "---------+" + END DO + WRITE(*,"(A)",advance='yes') "" + + DO i=1, nstacks + IF(csr_carrier%stackrow_descr(i)%defined_mnk) THEN + WRITE(*,"(A,I2,A,I2,A,I2,A)",advance='no') "|", & + csr_carrier%stackrow_descr(i)%m, " x ", & + csr_carrier%stackrow_descr(i)%n, " x ", & + csr_carrier%stackrow_descr(i)%k, " " + ELSE + WRITE(*,"(A)",advance='no') "| mixed " + END IF + + WRITE(*,"(A,I9,X)",advance='no') "| ", csr_carrier%stackrow_descr(i)%total_entries + DO j=1, n_stack_buffers + IF(csr_carrier%stackgrid_state(i,j)==dbcsr_ps_state_empty) THEN + WRITE(*,"(A,I7,A)",advance='no') "| ",csr_carrier%stackgrid_fillcount(i,j)," " + ELSE + WRITE(*,"(A,I1,A)",advance='no') "| busy(",csr_carrier%stackgrid_state(i,j),") " + END IF + END DO + WRITE(*,"(A)",advance='yes') "|" + END DO + + + +END SUBROUTINE print_stackgrid + ! ***************************************************************************** @@ -1015,7 +951,7 @@ MODULE dbcsr_mm_csr csr_norms(:) = 0.0_sp ENDIF END SUBROUTINE build_csr_index - + ! ***************************************************************************** !> \brief Determines whether a transpose must be applied !> \par Source @@ -1030,7 +966,7 @@ MODULE dbcsr_mm_csr transpose = BTEST(column+row, 0) .EQV. column.GE.row END FUNCTION my_checker_tr - + ! ----------------------------------------------------------------------------- ! Beginning of hashtable diff --git a/src/dbcsr_lib/dbcsr_mm_driver.F b/src/dbcsr_lib/dbcsr_mm_driver.F index 253bcb528d..be8a7a718d 100644 --- a/src/dbcsr_lib/dbcsr_mm_driver.F +++ b/src/dbcsr_lib/dbcsr_mm_driver.F @@ -5,378 +5,604 @@ ! ***************************************************************************** !> \brief Fourth layer of the dbcsr matrix-matrix multiplication. -!> It hides the differences between performing calculations on the -!> GPU or the CPU. +!> It hides the differences between performing calculations on the +!> GPU or the CPU. !> !> \author Urban Borstnik -!> +!> !> Modification history: !> - 2010-02-23 Moved from dbcsr_operations !> - 2011-11 Moved parameter-stack processing routines to !> dbcsr_mm_methods. -!> - 2013-01 reorganized code (Ole Schuett) +!> - 2013-01 extensive refactoring (Ole Schuett) ! ***************************************************************************** MODULE dbcsr_mm_driver - - USE dbcsr_block_operations, ONLY: block_add - USE dbcsr_config, ONLY: mm_driver,& + USE dbcsr_block_operations, ONLY: block_add,& + dbcsr_data_clear + USE dbcsr_config, ONLY: dbcsr_get_conf_nstacks,& + mm_driver,& mm_driver_cuda,& - mm_stack_size,& - mm_thread_workshare + mm_stack_size USE dbcsr_cuda_device, ONLY: dbcsr_cuda_create_streams,& - dbcsr_cuda_destroy_streams + dbcsr_cuda_destroy_streams,& + dbcsr_cuda_device_sync,& + dbcsr_cuda_init USE dbcsr_cuda_memory, ONLY: dbcsr_cuda_dev_mem_alloc,& - dbcsr_cuda_dev_mem_hold,& + dbcsr_cuda_dev_mem_dealloc,& dbcsr_cuda_dev_mem_new,& + dbcsr_cuda_dev_mem_realloc,& dbcsr_cuda_dev_mem_release,& - dbcsr_cuda_dev_mem_zero + dbcsr_cuda_dev_mem_zero,& + dbcsr_cuda_host_mem_alloc,& + dbcsr_cuda_host_mem_dealloc USE dbcsr_cuda_methods, ONLY: dbcsr_cuda_dev_mem_get_alloc USE dbcsr_cuda_operations, ONLY: dbcsr_cuda_cp_dev_to_host,& dbcsr_cuda_cp_host_to_dev - USE dbcsr_cuda_types, ONLY: dbcsr_cuda_mem_type + USE dbcsr_cuda_types, ONLY: dbcsr_cuda_mem_p_type,& + dbcsr_cuda_mem_type USE dbcsr_data_methods, ONLY: dbcsr_data_ensure_size,& dbcsr_data_get_size,& dbcsr_data_get_type,& dbcsr_data_init,& dbcsr_data_new,& - dbcsr_data_release + dbcsr_data_release,& + dbcsr_data_set_size_referenced USE dbcsr_error_handling - USE dbcsr_kinds, ONLY: int_4,& + USE dbcsr_kinds, ONLY: dp,& int_8,& real_8 - USE dbcsr_mm_types, ONLY: carrier_type - USE dbcsr_pq_methods, ONLY: dbcsr_ps_set_get_group_p,& - dbcsr_ps_target_add_data_cuda,& - dbcsr_psg_add_data_cuda_ab,& - dbcsr_psg_rm_data_cuda_ab - USE dbcsr_pq_types, ONLY: dbcsr_ps_group_type,& - dbcsr_ps_state_empty,& - dbcsr_ps_target_obj,& - dbcsr_ps_target_type,& - dbcsr_ps_width + USE dbcsr_mm_stack, ONLY: process_mm_stack_cpu,& + process_mm_stack_cuda + USE dbcsr_mm_types, ONLY: dbcsr_ps_state_empty,& + dbcsr_ps_state_working,& + dbcsr_ps_width,& + driver_carrier_type,& + stack_descriptor_type USE dbcsr_types, ONLY: dbcsr_data_obj,& dbcsr_type,& dbcsr_type_int_4 !$ USE OMP_LIB - + IMPLICIT NONE - + PRIVATE - + CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbcsr_mm_driver' - - PUBLIC :: dbcsr_mm_driver_outer_init, dbcsr_mm_driver_outer_finalize - PUBLIC :: dbcsr_mm_driver_inner_init - + + PUBLIC :: dbcsr_mm_driver_lib_init, dbcsr_mm_driver_lib_finalize + PUBLIC :: dbcsr_mm_driver_outer_init, dbcsr_mm_driver_outer_finalize + PUBLIC :: dbcsr_mm_driver_inner_init, dbcsr_mm_driver_inner_finalize + PUBLIC :: dbcsr_mm_driver_process_stack + + ! ===== Global Cuda Memory ===== + ! Allocating memory for cuda (on the card and host-pinned) is slow. + ! Therefore, the memory is allocated once and stored in global variables. + ! Variable cuda_mem_in_use should prevent concurred use of this global memory. + LOGICAL cuda_mem_in_use + !$OMP THREADPRIVATE(cuda_mem_in_use) + TYPE(dbcsr_cuda_mem_type), POINTER :: cuda_dev_c_data, cuda_dev_c_locks + !$OMP THREADPRIVATE(cuda_dev_c_data, cuda_dev_c_locks) + TYPE(dbcsr_cuda_mem_p_type), DIMENSION(:), POINTER :: cuda_dev_stacklist_data + !$OMP THREADPRIVATE(cuda_dev_stacklist_data) + INTEGER, DIMENSION(:,:,:,:), POINTER :: cuda_host_stackgrid_data + !$OMP THREADPRIVATE(cuda_host_stackgrid_data) + INTEGER, DIMENSION(:,:), POINTER :: cuda_host_stackgrid_state + !$OMP THREADPRIVATE(cuda_host_stackgrid_state) + + !These are shared between threads + TYPE(dbcsr_cuda_mem_type), POINTER, SAVE :: cuda_dev_a_data => Null() + TYPE(dbcsr_cuda_mem_type), POINTER, SAVE :: cuda_dev_b_data => Null() + TYPE(dbcsr_cuda_mem_type), POINTER, SAVE :: cuda_dev_state_empty => Null() + + + !INTEGER , SAVE :: num_cpu_stacks = 0 + !INTEGER , SAVE :: num_gpu_stacks = 0 + !INTEGER(kind=int_8), SAVE :: gpu_flop = 0 + !INTEGER(kind=int_8), SAVE :: cpu_flop = 0 + CONTAINS - - - + + ! ***************************************************************************** -!> \brief Moved out of internal_operations -!> This loads the data for matrizes A and B onto the card. -!> \author Ole Schuett +! \brief Initialize the library +! \author Ole Schuett ! ***************************************************************************** - SUBROUTINE dbcsr_mm_driver_inner_init(left, right, carrier, error) - TYPE(dbcsr_type), INTENT(IN) :: left, right - TYPE(carrier_type), INTENT(INOUT) :: carrier + SUBROUTINE dbcsr_mm_driver_lib_init(error) TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_driver_inner_init', & - routineP = moduleN//':'//routineN + INTEGER :: i, ithread, n_stack_buffers, & + nstacks, nthreads + INTEGER, DIMENSION(1), TARGET :: tmp_arr + INTEGER, DIMENSION(3) :: nxstacks + INTEGER, DIMENSION(:), POINTER :: tmp_ptr - IF (mm_driver .EQ. mm_driver_cuda) THEN - !$OMP MASTER - CALL dbcsr_cuda_cp_host_to_dev(& - left%data_area,& - carrier%param_sets%groups(1,1)%master%s%left_data_cuda,& - async = .TRUE.,& - error=error) - CALL dbcsr_cuda_cp_host_to_dev(& - right%data_area,& - carrier%param_sets%groups(1,1)%master%s%right_data_cuda,& - async = .TRUE.,& - error=error) - !$OMP END MASTER + nthreads = 1; ithread = 0 + !$ nthreads = OMP_GET_NUM_THREADS () ; ithread = OMP_GET_THREAD_NUM () + + IF (mm_driver == mm_driver_cuda) THEN + CALL dbcsr_get_conf_nstacks(nxstacks, n_stack_buffers, error) + nstacks = nxstacks(1) * nxstacks(2) * nxstacks(3) + 1 + + !Ensure that lock_offset in dbcsr_cuda_calc.cu won't overflow (it's a int4). + ! TODO: Check this code, before you start to used locking again. + IF(4*mm_stack_size > 2**17)& ! The "4" due to stack_mm_mnk_sq5_d + STOP "dbcsr_mm_driver_lib_init: mm_stack_size is too large" + IF(nthreads*nstacks*n_stack_buffers > 2**15)& + STOP "dbcsr_mm_driver_lib_init: nthreads*nstacks*n_stack_buffers is too large" + + !TODO: do we want to support multiple cards? Search: ma_set_gpu_affinity + CALL dbcsr_cuda_init(error=error) + + ! 1. Things that are shared between threads. + !----------------------------------------------------------------------- + !$OMP BARRIER + !$OMP MASTER + CALL dbcsr_cuda_create_streams(nthreads*nstacks*n_stack_buffers, error) + + ! Constant dbcsr_ps_state_empty needed on card to signal completed transfers. + tmp_arr = dbcsr_ps_state_empty + tmp_ptr => tmp_arr + CALL dbcsr_cuda_dev_mem_new(cuda_dev_state_empty, dbcsr_type_int_4, error=error) + CALL dbcsr_cuda_dev_mem_alloc(cuda_dev_state_empty, 1, error=error) + CALL dbcsr_cuda_cp_host_to_dev(host_mem=tmp_ptr, dev_mem=cuda_dev_state_empty%d_i, n=1,& + async=.FALSE.,error=error) + !$OMP END MASTER + !$OMP BARRIER + + ! 2. Things that are local to each thread + !------------------------------------------------------------------------ + ! Allocate the parameter stack on the card + ALLOCATE(cuda_dev_stacklist_data(nstacks*n_stack_buffers)) + DO i=1, nstacks*n_stack_buffers + NULLIFY(cuda_dev_stacklist_data(i)%p) + CALL dbcsr_cuda_dev_mem_new(cuda_dev_stacklist_data(i)%p, dbcsr_type_int_4, error) + CALL dbcsr_cuda_dev_mem_alloc(cuda_dev_stacklist_data(i)%p,& + dbcsr_ps_width*mm_stack_size, error=error) + END DO + + ! Allocate the parameter stack on the host with pinned memory + CALL dbcsr_cuda_host_mem_alloc(cuda_host_stackgrid_data, & + dbcsr_ps_width, mm_stack_size, nstacks, n_stack_buffers, error=error) + CALL dbcsr_cuda_host_mem_alloc(cuda_host_stackgrid_state, & + nstacks, n_stack_buffers, error=error) + + ! Size of the C-Blocks unkown at this point, allocation is done late. + NULLIFY(cuda_dev_c_data, cuda_dev_c_locks) + + !Setup safety guard against overlapping multiplications. + cuda_mem_in_use = .FALSE. ENDIF - - END SUBROUTINE dbcsr_mm_driver_inner_init - + + END SUBROUTINE dbcsr_mm_driver_lib_init + + ! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_init (actually csr_multiply_outer_init) -!> This allocates the memory for the matrizes A and B on the card and -!> and leaves pointers to them in every stack. +! \brief Finalize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_driver_lib_finalize(error) + USE ISO_C_BINDING + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + INTEGER :: i + + IF (mm_driver == mm_driver_cuda) THEN + ! Releasing host pinned memory of stackgrid on the host + CALL dbcsr_cuda_host_mem_dealloc(cuda_host_stackgrid_data, error) + CALL dbcsr_cuda_host_mem_dealloc(cuda_host_stackgrid_state, error) + + ! releasing stuff on the card if necessary + IF(ASSOCIATED(cuda_dev_c_data))& + CALL dbcsr_cuda_dev_mem_release(cuda_dev_c_data, error=error) + IF(ASSOCIATED(cuda_dev_c_locks))& + CALL dbcsr_cuda_dev_mem_release(cuda_dev_c_locks, error=error) + + DO i=1, SIZE(cuda_dev_stacklist_data) + CALL dbcsr_cuda_dev_mem_release(cuda_dev_stacklist_data(i)%p, error=error) + END DO + DEALLOCATE(cuda_dev_stacklist_data) + + !$OMP BARRIER + !$OMP MASTER + IF(ASSOCIATED(cuda_dev_a_data))& + CALL dbcsr_cuda_dev_mem_release(cuda_dev_a_data, error=error) + IF(ASSOCIATED(cuda_dev_b_data))& + CALL dbcsr_cuda_dev_mem_release(cuda_dev_b_data, error=error) + CALL dbcsr_cuda_dev_mem_release(cuda_dev_state_empty, error=error) + CALL dbcsr_cuda_destroy_streams(error=error) + + !How much memory is still allocated on the card? + !istat = dbcsr_cuda_dev_mem_info(mem_free, mem_avail) + !WRITE (*,*) "after outer_finalize cuda mem: ",mem_free, mem_avail, istat + !$OMP END MASTER + !$OMP BARRIER + + END IF + + + ! !$OMP MASTER + ! WRITE (*,*) "num_stacks gpu:", num_gpu_stacks, " cpu: ",num_cpu_stacks, " ratio: ",REAL(num_gpu_stacks)/REAL(num_cpu_stacks) + ! WRITE (*,*) "flop gpu:", gpu_flop, " cpu: ",cpu_flop, " ratio: ",REAL(gpu_flop)/REAL(cpu_flop) + ! !$OMP END MASTER + END SUBROUTINE dbcsr_mm_driver_lib_finalize + + + + +! ***************************************************************************** +!> \brief Initializes a multiplication cycle for new set of C-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE dbcsr_mm_driver_outer_init(left, right, product, product_target, carrier, fill_guess, error) + SUBROUTINE dbcsr_mm_driver_outer_init(left, right, product, drv_carrier,& + fill_guess, nstacks, n_stack_buffers, stackgrid_data, stackgrid_state, error) TYPE(dbcsr_type), INTENT(IN) :: left, right TYPE(dbcsr_type), INTENT(INOUT) :: product - TYPE(dbcsr_ps_target_obj), INTENT(INOUT) :: product_target - TYPE(carrier_type), INTENT(INOUT) :: carrier + TYPE(driver_carrier_type), INTENT(INOUT) :: drv_carrier REAL(KIND=real_8) :: fill_guess + INTEGER, INTENT(IN) :: nstacks, n_stack_buffers + INTEGER, DIMENSION(:, :, :, :), POINTER :: stackgrid_data + INTEGER, DIMENSION(:, :), POINTER :: stackgrid_state TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_driver_outer_init', & - routineP = moduleN//':'//routineN + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_driver_outer_init' - INTEGER :: data_type, nthreads, & - ps_buffer, ps_memreg - TYPE(dbcsr_cuda_mem_type), POINTER, SAVE :: a_dev, b_dev - TYPE(dbcsr_ps_group_type), POINTER :: ps_group + INTEGER :: a_data_size, allocated_datasize, b_data_size, c_data_size, & + c_locks_size, data_type, error_handler, ithread, nthreads, used_datasize - nthreads = 1 - !$ nthreads = OMP_GET_NUM_THREADS () - - - ! first driver init part --------------------------------------------------- + CALL dbcsr_error_set(routineN, error_handler, error) - IF (mm_driver .EQ. mm_driver_cuda) THEN - !$OMP MASTER - ! - ! Setup threads<->streams - CALL dbcsr_cuda_create_streams (nthreads, error) - ! - data_type = dbcsr_data_get_type (left%data_area) - CALL dbcsr_cuda_dev_mem_new (a_dev, data_type, error=error) - CALL dbcsr_cuda_dev_mem_new (b_dev, data_type, error=error) - CALL dbcsr_cuda_dev_mem_alloc (a_dev,& - dbcsr_data_get_size (left%data_area), error=error) - CALL dbcsr_cuda_dev_mem_alloc (b_dev,& - dbcsr_data_get_size (right%data_area), error=error) - !$OMP END MASTER - CALL init_card_c (product, product_target%t,fill_guess, error) - !$OMP BARRIER - IF (.FALSE.) THEN - ! Left in for mental accounting - !$OMP CRITICAL - CALL dbcsr_cuda_dev_mem_hold (a_dev, error=error) - CALL dbcsr_cuda_dev_mem_hold (b_dev, error=error) - !$OMP END CRITICAL - ENDIF + nthreads = 1; ithread = 0 + !$ nthreads = OMP_GET_NUM_THREADS () ; ithread = OMP_GET_THREAD_NUM () + + data_type = dbcsr_data_get_type(left%data_area) + + drv_carrier%product_wm => product%wms(ithread+1) !TODO: why do we need this ref? + used_datasize = drv_carrier%product_wm%datasize + allocated_datasize = dbcsr_data_get_size(drv_carrier%product_wm%data_area) + + ! The product's data_area could already contain some data. + ! ( see: keep_product_data in dbcsr_operations.F ) + ! But this data might not occupy all the allocated memory in the data_area. + ! Since, we don't want to keep track of unitialized memory we just zero it now. + CALL dbcsr_data_clear(drv_carrier%product_wm%data_area, lb=used_datasize+1, ub=allocated_datasize) + + IF (mm_driver /= mm_driver_cuda) THEN + ALLOCATE(stackgrid_data(dbcsr_ps_width, mm_stack_size, nstacks, n_stack_buffers)) + ALLOCATE(stackgrid_state(nstacks, n_stack_buffers)) ELSE - !$OMP MASTER - NULLIFY (a_dev, b_dev) - !$OMP END MASTER - !$OMP BARRIER - ENDIF - ! end of first part of driver init ----------------------------------------- - - ! second part of driver init ----------------------------------------------- - IF (mm_driver .EQ. mm_driver_cuda) THEN - DO ps_memreg = 1, carrier%param_sets%nmemregs - DO ps_buffer = 1, carrier%param_sets%nbuffers - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - !$OMP CRITICAL (crit_data_card) - CALL dbcsr_psg_add_data_cuda_ab (ps_group,& - a_dev, b_dev, error=error) - !$OMP END CRITICAL (crit_data_card) - ENDDO - ENDDO - IF (.FALSE.) THEN - ! Left in for mental accounting - !$OMP CRITICAL - CALL dbcsr_cuda_dev_mem_release (a_dev, error=error) - CALL dbcsr_cuda_dev_mem_release (b_dev, error=error) - !$OMP END CRITICAL - ENDIF + ! 0. Making shure there is only one multiplication going on at a time. + !------------------------------------------------------------------------ + IF(.NOT. ASSOCIATED(cuda_dev_state_empty)) & + STOP "dbcsr_mm_driver_outer_init: dbcsr not initialized" + IF(cuda_mem_in_use) STOP "dbcsr_mm_driver: found overlapping multiplications" + cuda_mem_in_use = .TRUE. + + ! 1. Things that are shared between threads. + !------------------------------------------------------------------------ !$OMP BARRIER !$OMP MASTER - CALL dbcsr_cuda_dev_mem_release (a_dev, error=error) - CALL dbcsr_cuda_dev_mem_release (b_dev, error=error) + ! (re)Allocate Memory for A and B blocks on the Card + a_data_size = dbcsr_data_get_size(left%data_area) + b_data_size = dbcsr_data_get_size(right%data_area) + CALL cuda_prepare_mem(cuda_dev_a_data, data_type, a_data_size, error=error) + CALL cuda_prepare_mem(cuda_dev_b_data, data_type, b_data_size, error=error) !$OMP END MASTER + !$OMP BARRIER + + + ! 2. Things that are local to each thread + !------------------------------------------------------------------------ + IF(SIZE(cuda_host_stackgrid_data, 1) /= dbcsr_ps_width .OR. & + SIZE(cuda_host_stackgrid_data, 2) /= mm_stack_size .OR. & + SIZE(cuda_host_stackgrid_data, 3) /= nstacks .OR. & + SIZE(cuda_host_stackgrid_data, 4) /= n_stack_buffers ) & + STOP "dbcsr_mm_driver_outer_init: cuda_host_stackgrid_data wrong dims" + + IF(SIZE(cuda_host_stackgrid_state, 1) /= nstacks .OR. & + SIZE(cuda_host_stackgrid_state, 2) /= n_stack_buffers ) & + STOP "dbcsr_mm_driver_outer_init: cuda_host_stackgrid_state wrong dims" + + stackgrid_data => cuda_host_stackgrid_data + stackgrid_state => cuda_host_stackgrid_state + + ! (re)Allocate Memory for C blocks on the Card and zero it. + c_data_size = dbcsr_data_get_size(product%wms(ithread+1)%data_area) + CALL cuda_prepare_mem(cuda_dev_c_data, data_type, c_data_size, zero=.TRUE., error=error) + + ! (re)Allocate and zero C locks on GPU. + c_locks_size = INT(product%nblkcols_local,KIND=int_8)* & + INT(product%nblkrows_local,KIND=int_8) * fill_guess + 1 + CALL cuda_prepare_mem(cuda_dev_c_locks, dbcsr_type_int_4, c_locks_size, zero=.TRUE., error=error) + ENDIF - + + CALL dbcsr_error_stop(error_handler, error) END SUBROUTINE dbcsr_mm_driver_outer_init - + ! ***************************************************************************** -!> \brief Moved out of dbcsr_multrec_finalize (actually csr_multiply_outer_finalize) -!> Copies the result matrix C back from the card, -!> deallocates the memory on the card, and destroys the streams. +! \brief Helper routine used by dbcsr_mm_driver_outer_init(). +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE cuda_prepare_mem(dev_mem, data_type, data_size, zero, error) + TYPE(dbcsr_cuda_mem_type), POINTER :: dev_mem + INTEGER, INTENT(IN) :: data_type, data_size + LOGICAL, INTENT(IN), OPTIONAL :: zero + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + IF (.NOT. ASSOCIATED(dev_mem)) THEN + !WRITE (*,*) "cuda_prepare_mem: allocting for the first time" + CALL dbcsr_cuda_dev_mem_new(dev_mem, data_type, error=error) + CALL dbcsr_cuda_dev_mem_alloc(dev_mem, data_size, error=error) + END IF + + IF (dev_mem%data_type /= data_type) THEN + !WRITE (*,*) "cuda_prepare_mem: changing datatype" + CALL dbcsr_cuda_dev_mem_release(dev_mem, error=error) + CALL dbcsr_cuda_dev_mem_new(dev_mem, data_type, error=error) + CALL dbcsr_cuda_dev_mem_alloc(dev_mem, data_size, error=error) + END IF + + IF (dbcsr_cuda_dev_mem_get_alloc(dev_mem) < data_size) THEN + !WRITE (*,*) "cuda_prepare_mem: growing dev_mem" + CALL dbcsr_cuda_dev_mem_dealloc(dev_mem, error=error) + CALL dbcsr_cuda_dev_mem_alloc(dev_mem, data_size, error=error) + END IF + + IF(PRESENT(zero)) THEN + IF(zero) CALL dbcsr_cuda_dev_mem_zero(dev_mem, first=1, & + last=dbcsr_cuda_dev_mem_get_alloc(dev_mem), error=error) + END IF + END SUBROUTINE + + +! ***************************************************************************** +!> \brief Initializes a multiplication cycle for a new set of A- and B-blocks. !> \author Ole Schuett ! ***************************************************************************** - SUBROUTINE dbcsr_mm_driver_outer_finalize(carrier, product, error) - TYPE(carrier_type), INTENT(INOUT) :: carrier - TYPE(dbcsr_type), INTENT(inout) :: product + SUBROUTINE dbcsr_mm_driver_inner_init(left, right, drv_carrier, error) + TYPE(dbcsr_type), INTENT(IN) :: left, right + TYPE(driver_carrier_type), INTENT(INOUT) :: drv_carrier TYPE(dbcsr_error_type), INTENT(INOUT) :: error - INTEGER :: data_size, data_type, & - ithread, ps_buffer, ps_memreg - TYPE(dbcsr_data_obj) :: tmp_data - TYPE(dbcsr_ps_group_type), POINTER :: ps_group + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_driver_inner_init' - IF (mm_driver .EQ. mm_driver_cuda) THEN - ! this part is from dbcsr_internal_operations --------------------------- - - ithread = 0 - !$ ithread = omp_get_thread_num() - - ! Transfer data from GPU to host. - CALL dbcsr_data_init (tmp_data) - CALL dbcsr_data_new (tmp_data,& - data_type = dbcsr_data_get_type(product%wms(ithread+1)%data_area),& - data_size = carrier%datasize) - CALL dbcsr_cuda_cp_dev_to_host(& - carrier%param_sets%groups(1,1)%master%s%t%t%product_data_cuda,& - !product%wms(1)%data_area,& - tmp_data,& - error=error) - CALL dbcsr_data_ensure_size(product%wms(ithread+1)%data_area,& - carrier%datasize, error=error) - CALL block_add (product%wms(ithread+1)%data_area, tmp_data,& - len=carrier%datasize, error=error) - CALL dbcsr_data_release (tmp_data) - ! end of part from dbcsr_internal_operations ---------------------------- - - ! this part is from dbcsr_multrec_finalize ------------------------------ - DO ps_memreg = 1, carrier%param_sets%nmemregs - DO ps_buffer = 1, carrier%param_sets%nbuffers - ps_group => dbcsr_ps_set_get_group_p (carrier%param_sets,& - ps_buffer, ps_memreg, error=error) - !$OMP CRITICAL (crit_data_card) - CALL dbcsr_psg_rm_data_cuda_ab (ps_group, error=error) - !$OMP END CRITICAL (crit_data_card) - ENDDO - ENDDO - ENDIF + INTEGER :: error_handler - !$OMP BARRIER - - !$OMP MASTER - IF (mm_driver .EQ. mm_driver_cuda) THEN - CALL dbcsr_cuda_destroy_streams (error=error) - ENDIF - !$OMP END MASTER - - END SUBROUTINE dbcsr_mm_driver_outer_finalize - - - -! ***************************************************************************** -!> \brief Perform allocations and setup needed for multiplication on an -!> accelerator card. -! ***************************************************************************** - SUBROUTINE init_card_c (host_matrix, product_target, fill_guess, error) - TYPE(dbcsr_type), INTENT(IN) :: host_matrix - TYPE(dbcsr_ps_target_type), & - INTENT(INOUT) :: product_target - REAL(KIND=real_8) :: fill_guess - TYPE(dbcsr_error_type), INTENT(INOUT) :: error + CALL dbcsr_error_set(routineN, error_handler, error) - CHARACTER(len=*), PARAMETER :: routineN = 'init_card_c', & - routineP = moduleN//':'//routineN + drv_carrier%left_data_area = left%data_area + drv_carrier%right_data_area = right%data_area - INTEGER :: clocks_size, data_size, & - data_type, error_handle, & - ithread - INTEGER, POINTER :: state_tmp - INTEGER, TARGET :: state_tmp_tgt - LOGICAL :: do_master_work - TYPE(dbcsr_cuda_mem_type), POINTER :: c_dev, c_locks_dev, & - params_dev_l - TYPE(dbcsr_cuda_mem_type), POINTER, SAVE :: params_dev, stack_state_dev - -! --------------------------------------------------------------------------- - - CALL dbcsr_error_set(routineN, error_handle, error) - - ! Only the master thread does common work in when threads share work. - do_master_work = .NOT. mm_thread_workshare - do_master_work = .TRUE. - !$OMP MASTER - do_master_work = .TRUE. - !$OMP END MASTER - - ithread = 0 - !$ ithread = OMP_GET_THREAD_NUM () - data_type = dbcsr_data_get_type (host_matrix%wms(ithread+1)%data_area) - data_size = dbcsr_data_get_size (host_matrix%wms(ithread+1)%data_area) - ! - ! Allocate space for product data on the card. - CALL dbcsr_cuda_dev_mem_new (c_dev, data_type, error) - CALL dbcsr_cuda_dev_mem_alloc (c_dev, data_size, error=error) - ! - ! To finish allocations before the zeroing is launched. - ! - !$OMP BARRIER - ! - ! Zero C data on card. This assumes that data will be - ! summed with the host data after the multiplication is done. - CALL dbcsr_cuda_dev_mem_zero(c_dev, first=1,& - last=data_size, error=error) - ! - ! Attach C data on card to the product target descriptor - CALL dbcsr_ps_target_add_data_cuda (product_target, c_dev, error) - CALL dbcsr_cuda_dev_mem_release (c_dev, error=error) - ! - ! Allocate C locks on GPU. Locks should be cleared as soon as - ! allocated. - CALL dbcsr_cuda_dev_mem_new (c_locks_dev,& - dbcsr_type_int_4, error) - clocks_size = INT(host_matrix%nblkcols_local,KIND=int_8)* & - INT(host_matrix%nblkrows_local,KIND=int_8)* & - fill_guess - clocks_size = MAX(1,INT(clocks_size, KIND=int_4)) - CALL dbcsr_cuda_dev_mem_alloc (c_locks_dev,INT(clocks_size,KIND=int_4), error=error) - CALL dbcsr_cuda_dev_mem_zero (c_locks_dev,& - first=1,last=dbcsr_cuda_dev_mem_get_alloc(c_locks_dev),& - error=error) - product_target%c_locks_dev => c_locks_dev - ! - ! Have a source from which to update states and setup the on-card - ! parameter stacks. - ! - !$OMP MASTER - CALL dbcsr_cuda_dev_mem_new (stack_state_dev, dbcsr_type_int_4,& - error=error) - CALL dbcsr_cuda_dev_mem_alloc (stack_state_dev, 1, error=error) - state_tmp_tgt = dbcsr_ps_state_empty - state_tmp => state_tmp_tgt - CALL dbcsr_cuda_cp_host_to_dev (state_tmp, stack_state_dev%d_i, error=error) - !$OMP END MASTER - IF (do_master_work) THEN - ! Allocate the on-card parameter stack. - CALL dbcsr_cuda_dev_mem_new (params_dev_l, dbcsr_type_int_4, error) - CALL dbcsr_cuda_dev_mem_alloc (params_dev_l, mm_stack_size*dbcsr_ps_width,& - error=error) + IF (mm_driver == mm_driver_cuda) THEN + !$OMP BARRIER !$OMP MASTER - params_dev => params_dev_l + !TODO: could be async if we use events to make the other streams wait + ! for a and b to be uploaded. + CALL dbcsr_cuda_cp_host_to_dev(host_mem=left%data_area,& + dev_mem=cuda_dev_a_data, async = .FALSE., error=error) + CALL dbcsr_cuda_cp_host_to_dev(host_mem=right%data_area,& + dev_mem=cuda_dev_b_data, async = .FALSE., error=error) !$OMP END MASTER + !$OMP BARRIER ENDIF - !$OMP BARRIER - !$OMP CRITICAL (crit_data_card) - ! - IF (.FALSE.) THEN - ! Left in for mental accounting - CALL dbcsr_cuda_dev_mem_hold (stack_state_dev, error=error) + + CALL dbcsr_error_stop(error_handler, error) + END SUBROUTINE dbcsr_mm_driver_inner_init + + +! ***************************************************************************** +!> \brief Finalizes a multiplication cycle for a set of A- and B-blocks. +!> \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_driver_inner_finalize(drv_carrier, error) + TYPE(driver_carrier_type), INTENT(INOUT) :: drv_carrier + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + IF (mm_driver == mm_driver_cuda) THEN + !TODO: waiting for ALL streams - should only wait for those of this thread + !$OMP BARRIER + CALL dbcsr_cuda_device_sync(error) + !$OMP BARRIER + END IF + END SUBROUTINE dbcsr_mm_driver_inner_finalize + + +! ***************************************************************************** +!> \brief Finalizes a multiplication cycle for a set of C-blocks. +!> \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_driver_outer_finalize(drv_carrier, product,stackgrid_data, stackgrid_state, error) + USE ISO_C_BINDING + TYPE(driver_carrier_type), INTENT(INOUT) :: drv_carrier + TYPE(dbcsr_type), INTENT(inout) :: product + INTEGER, DIMENSION(:, :, :, :), POINTER :: stackgrid_data + INTEGER, DIMENSION(:, :), POINTER :: stackgrid_state + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + INTEGER :: data_type, datasize, ithread + TYPE(dbcsr_data_obj) :: tmp_data + + ithread = 0 + !$ ithread = omp_get_thread_num() + + IF (mm_driver /= mm_driver_cuda) THEN + DEALLOCATE(stackgrid_data) + DEALLOCATE(stackgrid_state) + ELSE + ! Host-pinned memory not dealloced, will be reused by next multiplication + NULLIFY(stackgrid_data, stackgrid_state) + + ! Transfer C-data from GPU to host and adding it to host's result + datasize = product%wms(ithread+1)%datasize + data_type = dbcsr_data_get_type(product%wms(ithread+1)%data_area) + + CALL dbcsr_data_init(tmp_data) + CALL dbcsr_data_new(tmp_data, data_type=data_type, data_size=datasize) + CALL dbcsr_cuda_cp_dev_to_host(dev_mem=cuda_dev_c_data,& + host_mem=tmp_data, error=error) + CALL block_add(product%wms(ithread+1)%data_area, tmp_data,& + len=datasize, error=error) + CALL dbcsr_data_release(tmp_data) + + cuda_mem_in_use = .FALSE. ENDIF - ! all threads share the master's stack_state_dev - product_target%stack_state_dev => stack_state_dev - IF (do_master_work) THEN - product_target%params_dev => params_dev_l - ELSE - product_target%params_dev => params_dev - ENDIF - CALL dbcsr_cuda_dev_mem_hold (product_target%params_dev, error=error) - IF (.FALSE.) THEN - ! Left in for mental accounting - CALL dbcsr_cuda_dev_mem_release (stack_state_dev, error=error) - ENDIF - ! - !$OMP END CRITICAL (crit_data_card) - !$OMP BARRIER - IF (do_master_work) THEN - !$OMP CRITICAL (crit_data_card) - CALL dbcsr_cuda_dev_mem_release (params_dev_l, error=error) - !$OMP END CRITICAL (crit_data_card) - ENDIF - ! - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE init_card_c - - + END SUBROUTINE dbcsr_mm_driver_outer_finalize + + +! ***************************************************************************** +! \brief Processes a given stack. +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_driver_process_stack(drv_carrier, driver, stack_data,& + stack_fillcount, stack_state, stack_descr, stack_id, error) + TYPE(driver_carrier_type), INTENT(INOUT) :: drv_carrier + INTEGER, INTENT(IN) :: driver + INTEGER, DIMENSION(:, :), POINTER :: stack_data + INTEGER, POINTER :: stack_fillcount, stack_state + TYPE(stack_descriptor_type), POINTER :: stack_descr + INTEGER, INTENT(IN) :: stack_id + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + REAL, PARAMETER :: resize_factor = 1.618034 + + INTEGER :: allocated_datasize, nblks, & + new_c_size, new_locks_size, & + old_c_size, stacked_datasize + !INTEGER(kind=int_8) :: flop + +!TODO: make difference clear between driver, mm_driver and mm_host_driver. +! collect statistics + + stack_descr%total_entries = stack_descr%total_entries + stack_fillcount + + stacked_datasize = drv_carrier%product_wm%datasize + allocated_datasize = dbcsr_data_get_size(drv_carrier%product_wm%data_area) + + ! tell the data_area how much of its memory is actually beeing used. + CALL dbcsr_data_set_size_referenced(drv_carrier%product_wm%data_area, stacked_datasize) + + ! Resizing the product data (on host and card) --------------------------- + IF (stacked_datasize > allocated_datasize) THEN + + ! Resize the target data area if the stack references a target + ! matrix data element outside of its current range. When + ! appropriate a lock on the data area is taken. + !WRITE (*,*) "dbcsr_mm_driver_process_stack: We need to resize c data" + + !IF (dbg) & + ! WRITE(*,*)routineN//" Resizing to", LOG(REAL(maxs))/LOG(10.0) + CALL dbcsr_data_ensure_size(drv_carrier%product_wm%data_area,& + stacked_datasize, factor=resize_factor, zero_pad=.TRUE., error=error) + + IF(stacked_datasize > dbcsr_data_get_size(drv_carrier%product_wm%data_area))& + STOP "dbcsr_mm_driver_process_stack: resizing failed" + + ! Cuda on-device resizing + IF (mm_driver == mm_driver_cuda) THEN + ! All kernels in the stream must be finished before + ! reallocation is performed. + !TODO: waiting for ALL streams - should only wait for those of this thread + CALL dbcsr_cuda_device_sync(error) + + ! dbcsr_data_ensure_size oversizes the array - we need to know how much. + old_c_size = dbcsr_cuda_dev_mem_get_alloc(cuda_dev_c_data) + new_c_size = dbcsr_data_get_size(drv_carrier%product_wm%data_area) + CALL dbcsr_cuda_dev_mem_realloc(cuda_dev_c_data, new_c_size, error=error) + CALL dbcsr_cuda_dev_mem_zero(cuda_dev_c_data,& + first=old_c_size, last=new_c_size, error=error) + END IF + END IF + + ! Resizing the product locks (only on the card) -------------------------- + IF (mm_driver == mm_driver_cuda) THEN + ! Resize locks, which are equal to the new block count. + nblks = drv_carrier%product_wm%lastblk + IF (nblks > dbcsr_cuda_dev_mem_get_alloc(cuda_dev_c_locks)) THEN + !WRITE (*,*) "dbcsr_mm_driver_process_stack: We need to resize c_locks_cuda" + ! All kernels in the stream must be finished before + ! reallocation is performed. + !TODO: waiting for ALL streams - should only wait for those of this thread + CALL dbcsr_cuda_device_sync(error) + new_locks_size = INT(REAL(nblks*4,kind=dp)*resize_factor) + CALL dbcsr_cuda_dev_mem_realloc(cuda_dev_c_locks, new_locks_size, error=error) + CALL dbcsr_cuda_dev_mem_zero(cuda_dev_c_locks,& + first=1, last=new_locks_size, error=error) + END IF + END IF + + !!From here on there is no boundary checking due to assumed-SIZE-arguments. + !!This is usefull to check stack parameters, BUT it works only for kind=dp + !DO sp = 1, stack_fillcount + ! IF(stack_data(p_a_first,sp) > SIZE(drv_carrier%left_data_area%d%r_dp)) & + ! STOP "left data out of range" + ! IF(stack_data(p_b_first,sp) > SIZE(drv_carrier%right_data_area%d%r_dp)) & + ! STOP "right data out of range" + ! IF(stack_data(p_c_first,sp) > SIZE(drv_carrier%product_wm%data_area%d%r_dp)) THEN + ! WRITE (*,*) "blub: ",stack_data(p_c_first,sp) , SIZE(drv_carrier%product_wm%data_area%d%r_dp), & + ! dbcsr_data_get_size(drv_carrier%product_wm%data_area), stacked_datasize + ! STOP "product data out of range" + ! END IF + !END DO + + ! Submitting the stack for processing ------------------------------------- + stack_state = dbcsr_ps_state_working + + ! flop = 2*stack_fillcount*stack_descr%max_m*stack_descr%max_n*stack_descr%max_k + IF (driver == mm_driver_cuda) THEN + ! !$OMP critical + ! num_gpu_stacks = num_gpu_stacks + 1 + ! gpu_flop = gpu_flop + flop + ! !$OMP end critical + CALL process_mm_stack_cuda(params=stack_data,& + stack_size=stack_fillcount,& + data_a_dev=cuda_dev_a_data,& + data_b_dev=cuda_dev_b_data,& + data_c_dev=cuda_dev_c_data,& + c_locks=cuda_dev_c_locks,& + params_dev=cuda_dev_stacklist_data(stack_id)%p,& + m=stack_descr%m,& + n=stack_descr%n,& + k=stack_descr%k,& + max_m=stack_descr%max_m,& + max_n=stack_descr%max_n,& + max_k=stack_descr%max_k,& + defined_mnk=stack_descr%defined_mnk,& + state=stack_state,& + stack_state_dev=cuda_dev_state_empty,& + stack_id=stack_id,& + error=error) + ELSE + ! !$OMP critical + ! num_cpu_stacks = num_cpu_stacks + 1 + ! cpu_flop = cpu_flop + flop + ! !$OMP end critical + CALL process_mm_stack_cpu(params=stack_data,& + driver=driver,& + stack_size=stack_fillcount, & + left_data_area=drv_carrier%left_data_area,& + right_data_area=drv_carrier%right_data_area,& + product_data_area=drv_carrier%product_wm%data_area,& + state=stack_state,& + m=stack_descr%m,& + n=stack_descr%n,& + k=stack_descr%k,& + max_m=stack_descr%max_m,& + max_n=stack_descr%max_n,& + max_k=stack_descr%max_k,& + defined_mnk=stack_descr%defined_mnk,& + stack_id=stack_id,& + error=error) + END IF + + stack_fillcount = 0 !otherwise the stackcolumn gets processed again. + + + END SUBROUTINE dbcsr_mm_driver_process_stack + + END MODULE dbcsr_mm_driver + diff --git a/src/dbcsr_lib/dbcsr_mm_multrec.F b/src/dbcsr_lib/dbcsr_mm_multrec.F index 4f34289bab..bed183dd00 100644 --- a/src/dbcsr_lib/dbcsr_mm_multrec.F +++ b/src/dbcsr_lib/dbcsr_mm_multrec.F @@ -13,14 +13,13 @@ !> - 2010-02-23 Moved from dbcsr_operations !> - 2011-11 Moved parameter-stack processing routines to !> dbcsr_mm_methods. -!> - 2013-01 reorganized code (Ole Schuett) +!> - 2013-01 extensive refactoring (Ole Schuett) ! ***************************************************************************** MODULE dbcsr_mm_multrec USE array_types, ONLY: array_data,& array_equality - USE dbcsr_config, ONLY: mm_thread_workshare USE dbcsr_error_handling USE dbcsr_kinds, ONLY: int_8,& real_8,& @@ -31,29 +30,53 @@ MODULE dbcsr_mm_multrec dbcsr_distribution_local_rows,& dbcsr_distribution_row_dist,& dbcsr_distribution_thread_dist - USE dbcsr_mm_csr, ONLY: csr_multiply_inner_finalize,& - csr_multiply_inner_init,& - csr_multiply_outer_finalize,& - csr_multiply_outer_init,& - csr_multiply_unwrap - USE dbcsr_mm_types, ONLY: carrier_type + USE dbcsr_mm_csr, ONLY: dbcsr_mm_csr_inner_finalize,& + dbcsr_mm_csr_inner_init,& + dbcsr_mm_csr_lib_finalize,& + dbcsr_mm_csr_lib_init,& + dbcsr_mm_csr_multiply,& + dbcsr_mm_csr_outer_finalize,& + dbcsr_mm_csr_outer_init + USE dbcsr_mm_types, ONLY: multrec_carrier_type USE dbcsr_ptr_util, ONLY: ensure_array_size USE dbcsr_types, ONLY: dbcsr_type !$ USE OMP_LIB - + IMPLICIT NONE - + PRIVATE - + CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbcsr_mm_multrec' LOGICAL, PARAMETER :: careful_mod = .FALSE. - PUBLIC :: dbcsr_multrec_init - PUBLIC :: dbcsr_multrec_sparse - PUBLIC :: dbcsr_multrec_finalize - -CONTAINS + PUBLIC :: dbcsr_mm_multrec_lib_init, dbcsr_mm_multrec_lib_finalize + PUBLIC :: dbcsr_mm_multrec_init, dbcsr_mm_multrec_finalize + PUBLIC :: dbcsr_mm_multrec_multiply + + CONTAINS + +! ***************************************************************************** +! \brief Initialize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_multrec_lib_init(error) + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CALL dbcsr_mm_csr_lib_init(error) + END SUBROUTINE + + +! ***************************************************************************** +! \brief Finalize the library +! \author Ole Schuett +! ***************************************************************************** + SUBROUTINE dbcsr_mm_multrec_lib_finalize(error) + TYPE(dbcsr_error_type), INTENT(INOUT) :: error + + CALL dbcsr_mm_csr_lib_finalize(error) + END SUBROUTINE + ! ***************************************************************************** !> \brief Sets up recursive multiplication @@ -65,23 +88,18 @@ CONTAINS !> existing product matrix, default is no !> \param[in] eps (optional) on-the-fly filtering epsilon ! ***************************************************************************** - SUBROUTINE dbcsr_multrec_init(left, right, product, carrier,& - right_data_sr, right_data_rr, left_data_sr, left_data_rr, & - right_index_sr, right_index_rr, left_index_sr, left_index_rr, & + SUBROUTINE dbcsr_mm_multrec_init(left, right, product, multrec_carrier,& keep_sparsity, eps, row_max_epss, fill_guess, error) TYPE(dbcsr_type), INTENT(IN) :: left, right TYPE(dbcsr_type), INTENT(INOUT) :: product - TYPE(carrier_type), INTENT(out) :: carrier - INTEGER, DIMENSION(:, :), POINTER :: right_data_sr, right_data_rr, & - left_data_sr, left_data_rr, right_index_sr, right_index_rr, & - left_index_sr, left_index_rr + TYPE(multrec_carrier_type), INTENT(out) :: multrec_carrier LOGICAL, INTENT(IN) :: keep_sparsity REAL(kind=real_8), INTENT(in), OPTIONAL :: eps REAL(kind=sp), DIMENSION(:), INTENT(IN) :: row_max_epss REAL(KIND=real_8) :: fill_guess TYPE(dbcsr_error_type), INTENT(inout) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_multrec_init', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_multrec_init', & routineP = moduleN//':'//routineN LOGICAL, PARAMETER :: dbg = .FALSE. @@ -90,35 +108,30 @@ CONTAINS error_handler, i, ithread INTEGER, DIMENSION(:), POINTER :: c_local_cols, c_local_rows, & product_thread_dist - LOGICAL :: local_cols, local_indexing, & - local_rows ! --------------------------------------------------------------------------- CALL dbcsr_error_set(routineN, error_handler, error) - + ithread = 0 !$ ithread = OMP_GET_THREAD_NUM () - carrier%id = ithread ! ! Ensures that the index is correctly defined. CALL dbcsr_assert (left%list_indexing,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Must use list indexing for this routine.", __LINE__, error=error) - ! + CALL dbcsr_assert ("NOT", left%bcsc,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Wrong routine for BCSC matrices.", __LINE__, error=error) CALL dbcsr_assert ("NOT", right%bcsc,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Wrong routine for BCSC matrices.", __LINE__, error=error) - local_cols = right%local_indexing - local_rows = left%local_indexing - CALL dbcsr_assert (local_cols, "EQV", local_rows,& + CALL dbcsr_assert (right%local_indexing, "EQV", left%local_indexing,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Local index useage must be consistent.", __LINE__, error=error) - local_indexing = local_rows - IF (local_cols) THEN + + IF (right%local_indexing) THEN CALL dbcsr_assert (left%local_indexing,& dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& "Wrong left format for local_cols.", __LINE__, error=error) @@ -134,28 +147,18 @@ CONTAINS "Wrong right format for not local_cols.", __LINE__, error=error) ENDIF ! - ! Fill carrier data structure. - carrier%local_indexing = local_indexing - carrier%keep_sparsity = keep_sparsity - carrier%c_has_symmetry = product%symmetry - carrier%use_eps = PRESENT (eps) - carrier%my_wm = product%wms(ithread+1) - carrier%lastblk = product%wms(ithread+1)%lastblk - carrier%original_lastblk = carrier%lastblk - carrier%datasize = product%wms(ithread+1)%datasize - carrier%flop = INT(0, int_8) - carrier%right_data_sr => right_data_sr - carrier%right_data_rr => right_data_rr - carrier%right_index_sr => right_index_sr - carrier%right_index_rr => right_index_rr - carrier%left_data_sr => left_data_sr - carrier%left_data_rr => left_data_rr - carrier%left_index_sr => left_index_sr - carrier%left_index_rr => left_index_rr + ! Fill multrec_carrier data structure. + multrec_carrier%local_indexing = left%local_indexing + multrec_carrier%keep_sparsity = keep_sparsity + multrec_carrier%c_has_symmetry = product%symmetry + multrec_carrier%use_eps = PRESENT (eps) + multrec_carrier%original_lastblk = product%wms(ithread+1)%lastblk + multrec_carrier%flop = INT(0, int_8) + IF (PRESENT (eps)) THEN - carrier%eps = eps + multrec_carrier%eps = eps ELSE - carrier%eps = 0.0_real_8 + multrec_carrier%eps = 0.0_real_8 ENDIF ! ! @@ -171,17 +174,17 @@ CONTAINS c_local_rows => array_data (product%local_rows) c_nblkcols_local = product%nblkcols_local c_local_cols => array_data (product%local_cols) - IF (local_indexing) THEN - carrier%c_local_rows => c_local_rows - carrier%c_local_cols => c_local_cols + IF (multrec_carrier%local_indexing) THEN + multrec_carrier%c_local_rows => c_local_rows + multrec_carrier%c_local_cols => c_local_cols ELSE - ALLOCATE (carrier%c_local_rows (product%nblkrows_total)) - ALLOCATE (carrier%c_local_cols (product%nblkcols_total)) + ALLOCATE (multrec_carrier%c_local_rows (product%nblkrows_total)) + ALLOCATE (multrec_carrier%c_local_cols (product%nblkcols_total)) FORALL (i = 1 : product%nblkrows_total) - carrier%c_local_rows(i) = i + multrec_carrier%c_local_rows(i) = i END FORALL FORALL (i = 1 : product%nblkcols_total) - carrier%c_local_cols(i) = i + multrec_carrier%c_local_cols(i) = i END FORALL ENDIF IF (dbg) WRITE(*,*)"setting up for product", product%name @@ -213,54 +216,57 @@ CONTAINS ENDIF ! ! And the k epsilons - IF (local_indexing) THEN - ALLOCATE (carrier%row_max_epss(c_nblkrows_local)) + IF (multrec_carrier%local_indexing) THEN + ALLOCATE (multrec_carrier%row_max_epss(c_nblkrows_local)) ELSE - ALLOCATE (carrier%row_max_epss(product%nblkrows_total)) + ALLOCATE (multrec_carrier%row_max_epss(product%nblkrows_total)) ENDIF - IF (carrier%use_eps) THEN - IF (local_indexing) THEN + IF (multrec_carrier%use_eps) THEN + IF (multrec_carrier%local_indexing) THEN CALL local_filter_sp(row_max_epss, c_nblkrows_local, c_local_rows,& - carrier%row_max_epss) + multrec_carrier%row_max_epss) ELSE IF (careful_mod) & - CALL dbcsr_assert (SIZE(row_max_epss) .EQ. SIZE(carrier%row_max_epss),& + CALL dbcsr_assert (SIZE(row_max_epss) .EQ. SIZE(multrec_carrier%row_max_epss),& dbcsr_fatal_level, dbcsr_internal_error, routineN,& "max epss local/global mismatch.", __LINE__, error=error) - carrier%row_max_epss(:) = row_max_epss(:) + multrec_carrier%row_max_epss(:) = row_max_epss(:) ENDIF ELSE - carrier%row_max_epss(:) = -HUGE(0.0_sp) + multrec_carrier%row_max_epss(:) = -HUGE(0.0_sp) ENDIF ! - IF (local_indexing) THEN - ALLOCATE(carrier%m_sizes(c_nblkrows_local)) + IF (multrec_carrier%local_indexing) THEN + ALLOCATE(multrec_carrier%m_sizes(c_nblkrows_local)) CALL local_filter(array_data (product%row_blk_size), SIZE(c_local_rows),& - c_local_rows, carrier%m_sizes) - ALLOCATE(carrier%n_sizes(c_nblkcols_local)) + c_local_rows, multrec_carrier%m_sizes) + ALLOCATE(multrec_carrier%n_sizes(c_nblkcols_local)) CALL local_filter(array_data (product%col_blk_size), SIZE(c_local_cols),& - c_local_cols, carrier%n_sizes) + c_local_cols, multrec_carrier%n_sizes) ELSE - ALLOCATE(carrier%m_sizes(product%nblkrows_total)) - carrier%m_sizes(:) = array_data (product%row_blk_size) - ALLOCATE(carrier%n_sizes(product%nblkcols_total)) - carrier%n_sizes(:) = array_data (product%col_blk_size) + ALLOCATE(multrec_carrier%m_sizes(product%nblkrows_total)) + multrec_carrier%m_sizes(:) = array_data (product%row_blk_size) + ALLOCATE(multrec_carrier%n_sizes(product%nblkcols_total)) + multrec_carrier%n_sizes(:) = array_data (product%col_blk_size) ENDIF ! - NULLIFY (carrier%k_locals) - NULLIFY (carrier%k_sizes) - IF (.NOT. local_indexing) THEN - ALLOCATE (carrier%k_locals(right%nblkrows_total)) + NULLIFY (multrec_carrier%k_locals) + NULLIFY (multrec_carrier%k_sizes) + IF (.NOT. multrec_carrier%local_indexing) THEN + ALLOCATE (multrec_carrier%k_locals(right%nblkrows_total)) FORALL (i = 1:right%nblkrows_total) - carrier%k_locals(i) = i + multrec_carrier%k_locals(i) = i END FORALL - carrier%k_sizes => array_data (right%row_blk_size) + multrec_carrier%k_sizes => array_data (right%row_blk_size) ENDIF - - CALL csr_multiply_outer_init(left, right, product, carrier, fill_guess, error=error) - + + CALL dbcsr_mm_csr_outer_init(csr_carrier=multrec_carrier%csr_carrier, & + left=left, right=right, product=product,fill_guess=fill_guess,& + m_sizes=multrec_carrier%m_sizes, n_sizes=multrec_carrier%n_sizes,& + k_sizes=multrec_carrier%k_sizes, error=error) + CALL dbcsr_error_stop(error_handler, error) - END SUBROUTINE dbcsr_multrec_init + END SUBROUTINE dbcsr_mm_multrec_init ! ***************************************************************************** @@ -282,121 +288,85 @@ CONTAINS !> \param[out] flop (optional) number of effective double-precision !> floating point operations performed ! ***************************************************************************** - SUBROUTINE dbcsr_multrec_sparse(left, right, product, carrier, flop,& - keep_sparsity, a_norms, b_norms, eps, row_max_epss, error) + SUBROUTINE dbcsr_mm_multrec_multiply(left, right, product, multrec_carrier, flop,& + keep_sparsity, a_norms, b_norms, error) TYPE(dbcsr_type), INTENT(IN) :: left, right TYPE(dbcsr_type), INTENT(INOUT) :: product - TYPE(carrier_type), INTENT(inout) :: carrier + TYPE(multrec_carrier_type), & + INTENT(inout) :: multrec_carrier INTEGER(KIND=int_8), INTENT(OUT) :: flop LOGICAL, INTENT(IN) :: keep_sparsity REAL(kind=sp), DIMENSION(:), & INTENT(in), TARGET :: a_norms, b_norms - REAL(kind=real_8), INTENT(in), OPTIONAL :: eps - REAL(kind=sp), DIMENSION(:), & - INTENT(in), TARGET :: row_max_epss TYPE(dbcsr_error_type), INTENT(inout) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_multrec_sparse', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_multrec_multiply', & routineP = moduleN//':'//routineN LOGICAL, PARAMETER :: dbg = .FALSE. INTEGER :: ithread, nthreads, t_a_f, & t_a_l, t_b_f, t_b_l INTEGER, DIMENSION(:), POINTER :: k_locals - LOGICAL :: local_cols, local_indexing, & - local_rows ! --------------------------------------------------------------------------- -! ithread = 0 ; nthreads = 1 !$ ithread = OMP_GET_THREAD_NUM () ; nthreads = OMP_GET_NUM_THREADS () - carrier%flop = 0 - - CALL csr_multiply_inner_init(left, right, carrier, error=error) - - local_cols = right%local_indexing - local_rows = left%local_indexing - local_indexing = local_rows - + multrec_carrier%flop = 0 + + CALL dbcsr_mm_csr_inner_init(left=left, right=right, & + csr_carrier=multrec_carrier%csr_carrier, error=error) + ! Find out the local A columns / B rows and sizes ! The right%local_rows is setup by the communication engine. - IF (local_indexing) THEN + IF (multrec_carrier%local_indexing) THEN k_locals => array_data (right%local_rows) - carrier%k_locals => k_locals - CALL ensure_array_size (carrier%k_sizes, ub=SIZE(k_locals), error=error) + multrec_carrier%k_locals => k_locals + CALL ensure_array_size (multrec_carrier%k_sizes, ub=SIZE(k_locals), error=error) CALL local_filter(array_data(right%row_blk_size), SIZE(k_locals),& - k_locals, carrier%k_sizes) + k_locals, multrec_carrier%k_sizes) ELSE - k_locals => carrier%k_locals + k_locals => multrec_carrier%k_locals ENDIF ! Setup the block norms - carrier%a_norms => a_norms - carrier%b_norms => b_norms - ! - IF (mm_thread_workshare) THEN - !$OMP BARRIER - ENDIF - ! + multrec_carrier%a_norms => a_norms + multrec_carrier%b_norms => b_norms + + ! Start local multiplication - IF (.TRUE.) THEN - t_a_f = 1 - t_a_l = left%nblks - t_b_f = 1 - t_b_l = right%nblks - !$ ithread = OMP_GET_THREAD_NUM() - !$ t_a_f = left%thr_c(ithread+1)+1 - !$ t_a_l = left%thr_c(ithread+2) - IF (left%local_indexing) THEN - CALL sparse_multrec(& - 1, left%nblkrows_local,& - 1, right%nblkcols_local,& - 1, SIZE(k_locals),& - t_a_f, t_a_l, left%coo_l,& - t_b_f, t_b_l, right%coo_l,& - carrier, error, 0) - ELSE - CALL sparse_multrec(& - 1, left%nblkrows_total,& - 1, right%nblkcols_total,& - 1, SIZE(k_locals),& - t_a_f, t_a_l, left%coo_l,& - t_b_f, t_b_l, right%coo_l,& - carrier, error, 0) - ENDIF + t_a_f = 1 + t_a_l = left%nblks + t_b_f = 1 + t_b_l = right%nblks + !$ ithread = OMP_GET_THREAD_NUM() + !$ t_a_f = left%thr_c(ithread+1)+1 + !$ t_a_l = left%thr_c(ithread+2) + IF (multrec_carrier%local_indexing) THEN + CALL sparse_multrec(& + 1, left%nblkrows_local,& + 1, right%nblkcols_local,& + 1, SIZE(k_locals),& + t_a_f, t_a_l, left%coo_l,& + t_b_f, t_b_l, right%coo_l,& + product, multrec_carrier, error, 0) ELSE - ! For debugging. This avoids the recursion but it might not - ! work anymore. - IF (left%local_indexing) THEN - CALL csr_multiply_unwrap(& - 1, left%nblkrows_local,& - 1, right%nblkrows_local,& - 1, SIZE(k_locals),& - 1, left%nblks, left%row_p,& - 1, right%nblks, right%row_p,& - carrier, error) - ELSE - CALL csr_multiply_unwrap(& - 1, left%nblkrows_total,& - 1, right%nblkrows_total,& - 1, SIZE(k_locals),& - 1, left%nblks, left%row_p,& - 1, right%nblks, right%row_p,& - carrier, error) - ENDIF + CALL sparse_multrec(& + 1, left%nblkrows_total,& + 1, right%nblkcols_total,& + 1, SIZE(k_locals),& + t_a_f, t_a_l, left%coo_l,& + t_b_f, t_b_l, right%coo_l,& + product, multrec_carrier, error, 0) ENDIF + + CALL dbcsr_mm_csr_inner_finalize(csr_carrier=multrec_carrier%csr_carrier, error=error) + flop = multrec_carrier%flop ! - CALL csr_multiply_inner_finalize(carrier, error=error) - flop = carrier%flop - ! - IF (ASSOCIATED (carrier%k_sizes) .AND. carrier%local_indexing) & - DEALLOCATE (carrier%k_sizes) - ! - product%wms(ithread+1)%lastblk = carrier%lastblk - product%wms(ithread+1)%datasize = carrier%datasize - ! - END SUBROUTINE dbcsr_multrec_sparse - + IF (ASSOCIATED (multrec_carrier%k_sizes) .AND. multrec_carrier%local_indexing) & + DEALLOCATE (multrec_carrier%k_sizes) + + END SUBROUTINE dbcsr_mm_multrec_multiply + ! ***************************************************************************** !> \brief Sets up recursive multiplication @@ -408,12 +378,13 @@ CONTAINS !> existing product matrix, default is no !> \param[in] eps (optional) on-the-fly filtering epsilon ! ***************************************************************************** - SUBROUTINE dbcsr_multrec_finalize(carrier, product, error) - TYPE(carrier_type), INTENT(inout) :: carrier + SUBROUTINE dbcsr_mm_multrec_finalize(multrec_carrier, product, error) + TYPE(multrec_carrier_type), & + INTENT(inout) :: multrec_carrier TYPE(dbcsr_type), INTENT(inout) :: product TYPE(dbcsr_error_type), INTENT(inout) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_multrec_finalize', & + CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_mm_multrec_finalize', & routineP = moduleN//':'//routineN LOGICAL, PARAMETER :: dbg = .FALSE. @@ -422,64 +393,52 @@ CONTAINS ! --------------------------------------------------------------------------- CALL dbcsr_error_set(routineN, error_handler, error) - CALL csr_multiply_outer_finalize(carrier, product, error=error) - + CALL dbcsr_mm_csr_outer_finalize(csr_carrier=multrec_carrier%csr_carrier,& + product=product, error=error) + ithread = 0 !$ ithread = OMP_GET_THREAD_NUM() - - ! Release the carrier - DEALLOCATE (carrier%m_sizes) - DEALLOCATE (carrier%n_sizes) - DEALLOCATE (carrier%row_max_epss) - - IF (carrier%local_indexing) THEN - CALL remap_local2global(carrier%my_wm%row_i, carrier%my_wm%col_i,& - carrier%c_local_rows, carrier%c_local_cols,& - carrier%original_lastblk+1, carrier%lastblk) - ENDIF - ! - DEALLOCATE (carrier%m_size_maps) - DEALLOCATE (carrier%n_size_maps) - DEALLOCATE (carrier%k_size_maps) - DEALLOCATE (carrier%stack_map) - IF (.NOT. carrier%local_indexing) THEN - DEALLOCATE (carrier%c_local_rows) - DEALLOCATE (carrier%c_local_cols) - DEALLOCATE (carrier%k_locals) - NULLIFY (carrier%k_sizes) - ENDIF - ! - ! Reinstate WM - carrier%my_wm%lastblk = carrier%lastblk - carrier%my_wm%datasize = carrier%datasize - product%wms(ithread+1) = carrier%my_wm - NULLIFY(carrier%right_data_sr) - NULLIFY(carrier%right_data_rr) - NULLIFY(carrier%right_index_sr) - NULLIFY(carrier%right_index_rr) - NULLIFY(carrier%left_data_sr) - NULLIFY(carrier%left_data_rr) - NULLIFY(carrier%left_index_sr) - NULLIFY(carrier%left_index_rr) + ! Release the carrier + DEALLOCATE (multrec_carrier%m_sizes) + DEALLOCATE (multrec_carrier%n_sizes) + DEALLOCATE (multrec_carrier%row_max_epss) + + IF (multrec_carrier%local_indexing) THEN + CALL remap_local2global(product%wms(ithread+1)%row_i, & + product%wms(ithread+1)%col_i, & + multrec_carrier%c_local_rows, multrec_carrier%c_local_cols,& + multrec_carrier%original_lastblk+1, product%wms(ithread+1)%lastblk) + ENDIF ! + + IF (.NOT. multrec_carrier%local_indexing) THEN + DEALLOCATE (multrec_carrier%c_local_rows) + DEALLOCATE (multrec_carrier%c_local_cols) + DEALLOCATE (multrec_carrier%k_locals) + NULLIFY (multrec_carrier%k_sizes) + ENDIF + CALL dbcsr_error_stop(error_handler, error) - END SUBROUTINE dbcsr_multrec_finalize - - - + END SUBROUTINE dbcsr_mm_multrec_finalize + + + + ! ***************************************************************************** !> \brief Performs recursive multiplication !> \author Joost VandeVondele ! ***************************************************************************** RECURSIVE SUBROUTINE sparse_multrec(mi, mf, ni, nf, ki, kf,& ai, af, a_index, bi, bf, b_index, & - carrier, error, d) + product, carrier, error, d) INTEGER, INTENT(IN) :: mi, mf, ni, nf, ki, kf, ai, af INTEGER, DIMENSION(3, 1:af), INTENT(IN) :: a_index INTEGER, INTENT(IN) :: bi, bf INTEGER, DIMENSION(3, 1:bf), INTENT(IN) :: b_index - TYPE(carrier_type), INTENT(INOUT) :: carrier + TYPE(dbcsr_type), INTENT(INOUT) :: product + TYPE(multrec_carrier_type), & + INTENT(INOUT) :: carrier TYPE(dbcsr_error_type), INTENT(INOUT) :: error INTEGER, INTENT(IN) :: d @@ -502,13 +461,23 @@ CONTAINS RETURN ENDIF ENDIF + IF (af-ai+1 <= norec .AND. bf-bi+1 <= norec) THEN - CALL csr_multiply_unwrap(& - mi, mf, ni, nf, ki, kf,& - ai, af, a_index,& - bi, bf, b_index,& - carrier, error) - RETURN + IF (af-ai+1 .GT. 0 .AND. bf-bi+1 .GT. 0) & + CALL dbcsr_mm_csr_multiply(mi=mi, mf=mf,ni=ni, nf=nf, ki=ki, kf=kf,& + ai=ai, af=af, & + bi=bi, bf=bf,& + m_sizes=carrier%m_sizes, n_sizes=carrier%n_sizes, k_sizes=carrier%k_sizes,& + c_local_rows=carrier%c_local_rows, c_local_cols=carrier%c_local_cols,& + c_has_symmetry=carrier%c_has_symmetry, keep_sparsity=carrier%keep_sparsity,& + use_eps=carrier%use_eps, row_max_epss=carrier%row_max_epss,& + flop=carrier%flop,& + a_index=a_index, b_index=b_index,& + a_norms=carrier%a_norms, b_norms=carrier%b_norms,& + csr_carrier=carrier%csr_carrier, & + product=product,& + error=error) + RETURN ENDIF M = mf-mi + 1 @@ -525,9 +494,9 @@ CONTAINS s1=M/2 acut = find_cut_row(ai,af,a_index,mi+s1-1) CALL sparse_multrec(mi,mi+s1-1, ni,nf, ki,kf,& - ai,acut-1,a_index, bi,bf,b_index, carrier, error,d+1) + ai,acut-1,a_index, bi,bf,b_index, product, carrier, error,d+1) CALL sparse_multrec(mi+s1,mf, ni,nf, ki,kf,& - acut,af,a_index, bi,bf,b_index, carrier, error,d+1) + acut,af,a_index, bi,bf,b_index, product, carrier, error,d+1) CASE(2) s1=K/2 acut = find_cut_col(ai,af,a_index,ki+s1-1) @@ -541,9 +510,9 @@ CONTAINS WRITE(*,'(3(I7))')b_index ENDIF CALL sparse_multrec(mi,mf, ni,nf, ki,ki+s1-1,& - ai,acut-1,a_index, bi,bcut-1,b_index, carrier, error,d+1) + ai,acut-1,a_index, bi,bcut-1,b_index, product, carrier, error,d+1) CALL sparse_multrec(mi,mf, ni,nf, ki+s1,kf,& - acut,af,a_index, bcut,bf,b_index, carrier, error,d+1) + acut,af,a_index, bcut,bf,b_index, product, carrier, error,d+1) CASE(3) s1=N/2 bcut = find_cut_col(bi,bf,b_index,ni+s1-1) @@ -552,15 +521,15 @@ CONTAINS WRITE(*,'(3(I7))')b_index ENDIF CALL sparse_multrec(mi,mf, ni,ni+s1-1, ki,kf,& - ai,af,a_index, bi,bcut-1,b_index, carrier, error,d+1) + ai,af,a_index, bi,bcut-1,b_index, product, carrier, error,d+1) CALL sparse_multrec(mi,mf, ni+s1,nf, ki,kf,& - ai,af,a_index, bcut,bf,b_index, carrier, error,d+1) + ai,af,a_index, bcut,bf,b_index, product, carrier, error,d+1) END SELECT END SUBROUTINE sparse_multrec - + ! ****************************************************************************** -!> \brief +!> \brief !> \author JV ! ****************************************************************************** PURE FUNCTION find_cut_row(ai,af,a,val) RESULT(res) @@ -601,13 +570,13 @@ CONTAINS ! IF (a(i)%r>val) EXIT !ENDDO !res=i - END FUNCTION find_cut_row + END FUNCTION find_cut_row + - ! ****************************************************************************** -!> \brief +!> \brief !> \author JV -! ****************************************************************************** +! ****************************************************************************** PURE FUNCTION find_cut_col(ai,af,a,val) RESULT(res) INTEGER, INTENT(IN) :: ai, af INTEGER, DIMENSION(3, 1:af), INTENT(IN) :: a @@ -648,11 +617,11 @@ CONTAINS !res=i END FUNCTION find_cut_col - - + + ! ****************************************************************************** !> \brief Packs a globally-indexed array into a locally-indexed array. -! ****************************************************************************** +! ****************************************************************************** PURE SUBROUTINE remap_local2global(row_i, col_i, local_rows, local_cols,& first, last) INTEGER, INTENT(in) :: last, first @@ -727,7 +696,7 @@ CONTAINS local_data(l) = full_data(local_elements(l)) END FORALL END SUBROUTINE local_filter_sp - + END MODULE dbcsr_mm_multrec diff --git a/src/dbcsr_lib/dbcsr_mm_stack.F b/src/dbcsr_lib/dbcsr_mm_stack.F index dba0492f09..365ef81c84 100644 --- a/src/dbcsr_lib/dbcsr_mm_stack.F +++ b/src/dbcsr_lib/dbcsr_mm_stack.F @@ -13,43 +13,24 @@ ! - 2011-09-26 Split dbcsr_internal_operations ! ***************************************************************************** MODULE dbcsr_mm_stack - USE dbcsr_block_operations, ONLY: dbcsr_data_clear - USE dbcsr_config, ONLY: & - driver_is_async, mm_async, mm_driver, mm_driver_blas, mm_driver_cuda, & - mm_driver_matmul, mm_driver_plasma, mm_driver_smm, mm_thread_workshare - USE dbcsr_cuda_device, ONLY: dbcsr_cuda_device_sync,& - dbcsr_cuda_stream_sync - USE dbcsr_cuda_memory, ONLY: dbcsr_cuda_dev_mem_alloc,& - dbcsr_cuda_dev_mem_dealloc,& - dbcsr_cuda_dev_mem_realloc,& - dbcsr_cuda_dev_mem_zero - USE dbcsr_cuda_methods, ONLY: dbcsr_cuda_dev_mem_get_alloc + USE dbcsr_config, ONLY: driver_is_async,& + mm_driver_blas,& + mm_driver_matmul,& + mm_driver_plasma,& + mm_driver_smm USE dbcsr_cuda_operations, ONLY: dbcsr_cuda_cp_dev_to_host,& dbcsr_cuda_cp_host_to_dev,& dbcsr_cuda_do_mm_stack USE dbcsr_cuda_types, ONLY: dbcsr_cuda_mem_type - USE dbcsr_data_methods, ONLY: dbcsr_data_ensure_size,& - dbcsr_data_get_size,& - dbcsr_data_set_size_referenced + USE dbcsr_data_methods, ONLY: dbcsr_data_get_size USE dbcsr_error_handling USE dbcsr_kinds, ONLY: dp,& real_4,& real_8,& sp - USE dbcsr_pq_methods, ONLY: & - dbcsr_pq_add_stack, dbcsr_pq_flush_level_chg, dbcsr_pq_get_any_stack, & - dbcsr_pq_get_far_stack, dbcsr_pq_get_own_stack, & - dbcsr_pq_handoff_level_chg, dbcsr_ps_set_get_group_p, & - dbcsr_ps_set_get_n_working, dbcsr_ps_target_lock_main, & - dbcsr_ps_target_lock_regions, dbcsr_ps_target_new_regions, & - dbcsr_ps_target_unlock_main, dbcsr_ps_target_unlock_regions, & - dbcsr_psg_get_state, dbcsr_psg_set_state - USE dbcsr_pq_types, ONLY: & - dbcsr_pq_type, dbcsr_ps_group_type, dbcsr_ps_obj, dbcsr_ps_set_type, & - dbcsr_ps_state_empty, dbcsr_ps_state_queued, dbcsr_ps_state_working, & - dbcsr_ps_target_obj, dbcsr_ps_target_type, dbcsr_ps_type, & - dbcsr_ps_width, max_regions, p_a_first, p_b_first, p_c_first, p_k, & - p_m, p_n + USE dbcsr_mm_types, ONLY: & + dbcsr_ps_state_empty, dbcsr_ps_state_working, dbcsr_ps_width, & + p_a_first, p_b_first, p_c_first, p_k, p_m, p_n USE dbcsr_toollib, ONLY: sort USE dbcsr_types, ONLY: dbcsr_data_obj,& dbcsr_type_complex_4,& @@ -76,548 +57,13 @@ MODULE dbcsr_mm_stack LOGICAL, PARAMETER, PUBLIC :: show_levels = .FALSE. LOGICAL, PARAMETER :: verbose_acc = .FALSE. - PUBLIC :: enqueue_ps_group - PUBLIC :: process_queue_mine,& - process_queue_others,& - process_queue_preempt,& - get_stack_or_process_queue - + PUBLIC :: process_mm_stack_cpu, process_mm_stack_cuda LOGICAL, PARAMETER :: debug_mod = .FALSE. LOGICAL, PARAMETER :: careful_mod = .FALSE. - !> \var max_stack_block_size The maximal block size to be specially - !> treated. - INTEGER, PARAMETER :: max_stack_block_size = HUGE (INT (0)) - - !$ INTEGER(KIND=omp_lock_kind), SAVE :: accel_lock - CONTAINS -! ***************************************************************************** -!> \brief Puts stacks ready to be processed into a queue -!> -!> All non-empty stacks in the param_group are added to the queue. -!> \par Non-worksharing -!> When mm_thread_workshare is FALSE the stacks are instead processessed -!> immediately, bypassing the queue. -!> \param[in,out] queue My queue, to which parameter stacks are added. -!> \param[in] param_group Parameter stacks to add to queue -!> \param[in,out] error error -!> \note The queue and param_groups parameters could be INTENT(INOUT) -!> when OpenMP is not used. -! ***************************************************************************** - SUBROUTINE enqueue_ps_group (queue, param_group, error) - TYPE(dbcsr_pq_type), POINTER :: queue - TYPE(dbcsr_ps_group_type), POINTER :: param_group - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'enqueue_ps_group', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod, & - dbg = debug_mod - - INTEGER :: error_handle, i - - IF (careful_mod) & - CALL dbcsr_error_set(routineN, error_handle, error) - CALL dbcsr_psg_set_state (param_group, dbcsr_ps_state_queued, error) - param_group%master%s%driver = mm_driver - !$ if (dbg) write(*,*)" lckng targt", OMP_GET_THREAD_NUM(),& - !$ param_group%master%s%t%t%owner - CALL process_ps_target_low (param_group%master%s%t,& - param_group%master%s%t%t%product_data_area,& - param_group%master%s%t%t%zero_first,& - param_group%master%s%t%t%zero_last,& - param_group%master%s%t%t%last_c_blk,& - param_group%master%s%driver,& - param_group%master%s%t%t%product_data_cuda,& - param_group%master%s%t%t%c_locks_dev,& - error) - DO i = SIZE(param_group%stacks), 1, -1 - param_group%stacks(i)%s%driver = mm_driver - IF (param_group%stacks(i)%s%stack_p .EQ. 0) THEN - param_group%stacks(i)%s%state = dbcsr_ps_state_empty - IF (dbg) WRITE(*,*)routineN//" not adding empty stack" - ELSE - IF (dbg) WRITE(*,*)routineN//" adding stack len", param_group%stacks(i)%s%stack_p - IF (mm_thread_workshare .OR. mm_async) THEN - CALL dbcsr_pq_add_stack (queue, param_group%stacks(i), error=error) - ELSE - ! If no worksharing is active, just process the stack immediately. - param_group%stacks(i)%s%driver = mm_driver - CALL process_ps_stack (param_group%stacks(i)%s, error=error) - ENDIF - ENDIF - ENDDO - IF (careful_mod) & - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE enqueue_ps_group - - -! ***************************************************************************** -!> \brief Processes stacks from my queue -!> -!> \param[in,out] queue My queue -!> \param[in] driver Driver to use for processing queue -!> \param[in,out] error error -!> \note The queue parameter could be INTENT(INOUT) when OpenMP is not used. -! ***************************************************************************** - SUBROUTINE process_queue_mine (queue, driver, error) - TYPE(dbcsr_pq_type), POINTER :: queue - INTEGER, INTENT(IN) :: driver - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'process_queue_mine', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod, & - dbg = debug_mod - - INTEGER :: cnt, error_handle, max_handoff - LOGICAL :: easy, found - TYPE(dbcsr_ps_obj) :: stack - - IF (careful_mod) & - CALL dbcsr_error_set(routineN, error_handle, error) - easy = driver_is_async (driver) - cnt = 0 - IF (easy) THEN - max_handoff = queue%handoff - queue%nworking - ENDIF - DO - CALL dbcsr_pq_get_own_stack (queue, stack, found,& - easy = easy, error=error) - IF (dbg) THEN - !$omp master - WRITE(*,*)"Found my stack" - !$omp end master - ENDIF - IF (found) THEN - stack%s%driver = driver - CALL process_ps_stack(stack%s, error=error) - cnt = cnt + 1 - IF (easy .AND. cnt .GT. max_handoff) EXIT - ELSE - EXIT - ENDIF - ENDDO - ! - IF (careful_mod) & - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE process_queue_mine - - -! ***************************************************************************** -!> \brief Processes stacks from other threads -!> -!> \param[in,out] queue My queue -!> \param[in] forever Processes until all other threads declare -!> they are done. -!> \param[in] driver Driver to use for processing queue -!> \param[in,out] error error -!> \note The queue parameter could be INTENT(INOUT) when OpenMP is not used. -! ***************************************************************************** - SUBROUTINE process_queue_others (queue, forever, driver, error) - TYPE(dbcsr_pq_type), POINTER :: queue - LOGICAL, INTENT(IN) :: forever - INTEGER, INTENT(IN) :: driver - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'process_queue_others', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod, & - dbg = debug_mod - - INTEGER :: cnt, error_handle, nt, & - old_thread_ptr, t, thread_ptr - LOGICAL :: easy, found, keep_cycling - TYPE(dbcsr_ps_obj) :: stack - - IF (careful_mod) & - CALL dbcsr_error_set(routineN, error_handle, error) - ! - ! - nt = 1 - !$nt = omp_get_num_threads() - easy = driver_is_async (driver) - cnt = 1 - old_thread_ptr = 0 - thread_ptr = 1 - found = .TRUE. - keep_cycling = found .OR.& - (forever .AND. queue%all_queues%n_working .GT. 0) - DO WHILE (keep_cycling) - CALL dbcsr_pq_get_any_stack (queue, stack, found,& - easy = easy,& - anyways = easy,& - thread_ptr = thread_ptr, error=error) - IF (thread_ptr .NE. old_thread_ptr) cnt = 1 - old_thread_ptr = thread_ptr - IF (found) THEN - IF (dbg) THEN - !$omp master - WRITE(*,*)"Found other stack owned by", stack%s%t%t%owner - !$omp end master - ENDIF - stack%s%driver = driver - CALL process_ps_stack(stack%s, error=error) - cnt = cnt + 1 - t = 0 - !$ t = omp_get_thread_num () - t = MOD(thread_ptr + t, nt)+1 - IF (easy .AND.& - cnt .GT. queue%all_queues%queues(t)%pq%handoff& - - queue%all_queues%queues(t)%pq%nworking) THEN - thread_ptr = thread_ptr + 1 - WRITE(*,*)'new thread', thread_ptr - ENDIF - ENDIF - !$OMP FLUSH - keep_cycling = found .OR.& - (forever .AND. queue%all_queues%n_working .GT. 0) - ENDDO - ! - IF (careful_mod) & - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE process_queue_others - - -! ***************************************************************************** -!> \brief Processes stacks while the accelerator processor is busy. -!> -!> Processing is not done if number of stacks being processed is less -!> than the queue's flush_level. -!> \see get_stack_or_process_queue -!> \see csr_multiply -!> \param[in,out] queue My queue -!> \param[in,out] param_sets Parameter group sets -!> \param[in] driver Driver to use for processing queue -!> \param[in,out] error error -!> \note The queue parameter could be INTENT(INOUT) when OpenMP is not used. -! ***************************************************************************** - SUBROUTINE process_queue_preempt (queue, param_set, driver, error) - TYPE(dbcsr_pq_type), POINTER :: queue - TYPE(dbcsr_ps_set_type), INTENT(INOUT) :: param_set - INTEGER, INTENT(IN) :: driver - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'process_queue_preempt', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod, & - dbg = debug_mod - - INTEGER :: error_handle, iam, n - LOGICAL :: found - TYPE(dbcsr_ps_obj) :: stack - - IF (careful_mod) & - CALL dbcsr_error_set(routineN, error_handle, error) - ! - ! Fetch & process only if no one else is done (i.e., has spare - ! time to process my stacks). - found = .TRUE. - n = dbcsr_ps_set_get_n_working (param_set, error) - !$ if (.FALSE. .AND. dbg) & - !$ write(*,*)routineN, omp_get_thread_num(), n, queue%flush_level - DO WHILE (n .GT. queue%flush_level .AND. found) - CALL dbcsr_pq_get_far_stack (queue, stack, found, error=error) - IF (found) THEN - IF (dbg) THEN - iam = 0 - !$ iam = omp_get_thread_num () - WRITE(*,*)"Preempt: Found own stack", iam - ENDIF - stack%s%driver = driver - CALL process_ps_stack(stack%s, error=error) - ENDIF - IF (dbg) THEN - n = dbcsr_ps_set_get_n_working (param_set, error) - IF (n .EQ. 0) WRITE(*,*)"oops" - ENDIF - ENDDO - ! - IF (careful_mod) & - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE process_queue_preempt - - -! ***************************************************************************** -!> \brief Gets a new stack group prepared for writing. -!> \par Dealing with busy stack groups. -!> The queue will be processed while the stack group is busy (it is -!> queued or in processing). -!> -!> If the stack_group is not immediately available the queue's -!> flush_level is lowered. It thus becomes more favorable to have the -!> host CPU process stacks. -!> \see process_queue_preempt -!> \see csr_multiply -!> \param[in,out] param_sets The parameter group sets -!> \param[in,out] queue My queue -!> \param[out] stack_group Retrieved stack group -!> \param[in] driver Driver to use for processing queue -!> \param[in,out] error error -!> \note The queue parameter could be INTENT(INOUT) when OpenMP is not used. -! ***************************************************************************** - SUBROUTINE get_stack_or_process_queue (param_sets, queue, stack_group,& - driver, error) - TYPE(dbcsr_ps_set_type), INTENT(INOUT) :: param_sets - TYPE(dbcsr_pq_type), POINTER :: queue - TYPE(dbcsr_ps_group_type), POINTER :: stack_group - INTEGER, INTENT(IN) :: driver - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - LOGICAL, PARAMETER :: dbg = debug_mod - - INTEGER :: cnt, n, stack_state - LOGICAL :: found - TYPE(dbcsr_ps_obj) :: stack - - stack_group => dbcsr_ps_set_get_group_p (param_sets, wait=.FALSE.,& - error=error) - IF (mm_thread_workshare) THEN - !$OMP FLUSH - ENDIF - ! If the parameter stack we get is still busy then - ! just do more crunching. - cnt = 1 - stack_state = dbcsr_psg_get_state (stack_group, error) - IF (stack_state .GE. dbcsr_ps_state_queued .AND. mm_async) THEN - ! The parameter stack is still busy. The others processors are - ! too slow so we lower the threshold for local computation. - ! - !$ if (dbg) write(*,*)"still in queue:", queue%nstacks, omp_get_thread_num() - n = dbcsr_ps_set_get_n_working (param_sets, error) - CALL dbcsr_pq_flush_level_chg (queue, -(n/4),& - param_sets) - CALL dbcsr_pq_handoff_level_chg (queue, -MAX((param_sets%group_size*3)/2,1),& - param_sets) - ENDIF - DO WHILE (stack_state .GE. dbcsr_ps_state_queued) - ! Just process the queue until the parameter stack is clear. - CALL dbcsr_pq_get_far_stack (queue, stack, found, error=error) - IF (found) THEN - stack%s%driver = driver - CALL process_ps_stack(stack%s, error=error) - ENDIF - IF (mm_thread_workshare) THEN - !$OMP FLUSH - ENDIF - cnt = cnt + 1 - stack_state = dbcsr_psg_get_state (stack_group, error) - ENDDO - END SUBROUTINE get_stack_or_process_queue - - -! ***************************************************************************** -!> \brief Prepares the target for stack processing. -!> \note Resizes data area, zeros new data, resets device locks, ... -! ***************************************************************************** - SUBROUTINE process_ps_target_low (target_desc,& - product_data_area,& - zero_first, zero_last, nblks, driver, card_data, c_locks_dev, error) - TYPE(dbcsr_ps_target_obj), INTENT(INOUT) :: target_desc - TYPE(dbcsr_data_obj), INTENT(INOUT) :: product_data_area - INTEGER, INTENT(INOUT) :: zero_first, zero_last - INTEGER, INTENT(IN) :: nblks, driver - TYPE(dbcsr_cuda_mem_type), POINTER :: card_data, c_locks_dev - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'process_ps_target_low', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod, & - dbg = debug_mod, & - info = .FALSE. - REAL, PARAMETER :: resize_factor = 1.618034 - - INTEGER :: c_size, istat, maxs, tmp_i - LOGICAL :: stream_is_synced - -! --------------------------------------------------------------------------- -! -! Resize target data area if necessary. -! Here we want the actual allocation size. - - maxs = dbcsr_data_get_size(product_data_area) - IF (zero_last .GT. maxs) THEN - ! Resize the target data area if the stack references a target - ! matrix data element outside of its current range. When - ! appropriate a lock on the data area is taken. - IF (dbg) WRITE(*,*)"Target too small" - maxs = zero_last - IF (mm_thread_workshare) THEN - ! Lock the target and wait for others to unlock their - ! regions. - CALL dbcsr_ps_target_lock_main (target_desc%t,& - flush=.TRUE.,& - error=error) - ENDIF - IF (dbg) & - WRITE(*,*)routineN//" Resizing to", LOG(REAL(maxs))/LOG(10.0) - CALL dbcsr_data_ensure_size (product_data_area,& - maxs, factor=resize_factor, error=error) - IF (mm_thread_workshare) THEN - ! Potentially resize locks. The number of region locks is - ! adjusted to the allocated size of the new data area (to - ! prevent changing them whenever the last addressed block is - ! changed). - maxs = dbcsr_data_get_size(product_data_area) - CALL dbcsr_ps_target_new_regions (target_desc%t,& - maxs, error=error) - CALL dbcsr_ps_target_unlock_main (target_desc%t, error) - ENDIF - ENDIF - IF (dbg) WRITE(*,*)"Setting referenced size" - CALL dbcsr_data_set_size_referenced (product_data_area, zero_last) - IF (dbg) WRITE(*,*)"Done" - ! - ! Zero new blocks - IF (zero_last .GE. zero_first) THEN - IF (dbg) WRITE(*,*)"Zeroing" - CALL dbcsr_data_clear (product_data_area, lb=zero_first, ub=zero_last) - IF (dbg) WRITE(*,*)"Done" - ENDIF - ! - ! Cuda on-device resizing - cuda_process_target: IF (driver .EQ. mm_driver_cuda) THEN - stream_is_synced = .FALSE. - IF (dbg) WRITE(*,*)"Getting allocated size..." - !$ IF (dbg) WRITE(*,*)"thread, target", omp_get_thread_num(),& - !$ target_desc%t%owner - c_size = dbcsr_cuda_dev_mem_get_alloc(card_data) - IF (dbg) WRITE(*,*)"done", c_size, "vs", zero_last - ! Resize & zero product data if too big. - IF (zero_last .GT. c_size) THEN - ! - ! All kernels in the stream must be finished before - ! reallocation is performed. - CALL dbcsr_cuda_stream_sync (target_desc%t%owner+1, error=error) - stream_is_synced = .TRUE. - IF (dbg .OR. info) WRITE(*,*)routineN//" reallocating c_dev",& - c_size, zero_last - tmp_i = MAX(zero_last, INT(REAL(zero_last)*resize_factor) ) - IF (verbose_acc) WRITE(*,*)routineN//" reallocating c_dev",& - tmp_i, c_size - !--- !$OMP CRITICAL (crit_cuda) - !$ IF (mm_thread_workshare) CALL OMP_SET_LOCK (accel_lock) - CALL dbcsr_cuda_dev_mem_realloc (card_data, tmp_i, stat=istat) - IF (istat /= 0) THEN - ! If the resize, including pre-oversizing failed, try to - ! resize it to the actual number of locks used. - IF (verbose_acc) WRITE(*,*)routineN//" Running out of memory" - CALL dbcsr_cuda_dev_mem_realloc (card_data, zero_last, stat=istat) - ENDIF - c_size = dbcsr_cuda_dev_mem_get_alloc(card_data) - IF (dbg) WRITE(*,*)routineN//" zeroing c_dev" - CALL dbcsr_cuda_dev_mem_zero(card_data,& - first=zero_first, last=c_size, error=error) - !$ IF (mm_thread_workshare) CALL OMP_UNSET_LOCK (accel_lock) - !--- !$OMP END CRITICAL (crit_cuda) - ELSE IF (dbg) THEN - WRITE(*,*)"not reallocating c_dev" - ENDIF - ! - ! Resize locks, which are equal to the new block count. - IF (dbg) WRITE(*,*)routineN//" lock size..." - IF (dbg) WRITE(*,*)routineN, dbcsr_cuda_dev_mem_get_alloc(c_locks_dev) - IF (nblks .GT. dbcsr_cuda_dev_mem_get_alloc(c_locks_dev)) THEN - ! - ! All kernels in the stream must be finished before - ! reallocation is performed. - IF (.NOT. stream_is_synced) THEN - CALL dbcsr_cuda_stream_sync (target_desc%t%owner+1, error=error) - ENDIF - stream_is_synced = .TRUE. - IF (dbg) WRITE(*,*)routineN//" reallocing locks" - maxs = dbcsr_cuda_dev_mem_get_alloc(c_locks_dev) - IF (dbg) WRITE(*,*)routineN//" lock size", maxs - IF (dbg) WRITE(*,*)routineN//" reallocing locks" - IF (verbose_acc .OR. info) WRITE(*,*)routineN//" reallocating locks", maxs - IF (dbg) WRITE(*,*)routineN//" deallocating..." - !--- !$OMP CRITICAL (crit_cuda) - !$ IF (mm_thread_workshare) CALL OMP_SET_LOCK (accel_lock) - CALL dbcsr_cuda_dev_mem_dealloc(c_locks_dev, error=error) - tmp_i = INT(REAL(nblks*4,kind=dp)*default_resize_factor) - !WRITE(*,*)routineN//" reallocating locks", tmp_i, maxs - IF (dbg) WRITE(*,*)routineN//" allocating..." - CALL dbcsr_cuda_dev_mem_alloc(c_locks_dev, tmp_i, stat=istat) - IF (istat /= 0) THEN - IF (verbose_acc) WRITE(*,*)routineN//" Trying smaller allocation" - tmp_i = nblks - IF (dbg) WRITE(*,*)routineN//" failed, trying smaller..." - CALL dbcsr_cuda_dev_mem_alloc(c_locks_dev, tmp_i, error=error) - ENDIF - IF (dbg) WRITE(*,*)routineN//" zeroing..." - CALL dbcsr_cuda_dev_mem_zero(c_locks_dev,& - first=1, last=dbcsr_cuda_dev_mem_get_alloc(c_locks_dev),& - error=error) - !$ IF (mm_thread_workshare) CALL OMP_UNSET_LOCK (accel_lock) - !--- !$OMP END CRITICAL (crit_cuda) - !write(*,*)routineN//" done zeroing" - ENDIF - ENDIF cuda_process_target - IF (dbg) WRITE(*,*)routineN//" done" - zero_first = zero_last + 1 - END SUBROUTINE process_ps_target_low - - -! ***************************************************************************** -!> \brief Unpacks stack variables to call lower-level stack processing -!> drivers. -!***************************************************************************** - SUBROUTINE process_ps_stack(param_stack, error) - TYPE(dbcsr_ps_type), INTENT(INOUT) :: param_stack - TYPE(dbcsr_error_type), INTENT(INOUT) :: error - - CHARACTER(len=*), PARAMETER :: routineN = 'process_ps_stack', & - routineP = moduleN//':'//routineN - LOGICAL, PARAMETER :: careful = careful_mod - - INTEGER :: error_handle, stack_size - - IF (careful_mod) & - CALL dbcsr_error_set(routineN, error_handle, error) - IF (careful_mod) THEN - IF (param_stack%driver .EQ. mm_driver_cuda) THEN - CALL dbcsr_assert (param_stack%has_cuda_ab_data,& - dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& - "A or B matrix data not present in stack.",& - __LINE__, error=error) - ELSE - CALL dbcsr_assert (param_stack%has_ab_data,& - dbcsr_fatal_level, dbcsr_wrong_args_error, routineN,& - "A or B matrix data not present in stack.",& - __LINE__, error=error) - ENDIF - ENDIF - !if (dbg) & - ! write(*,*)routineN, OMP_GET_THREAD_NUM(), param_stack%stack_p,& - ! param_stack%id, param_stack%sid, param_stack%t%t%owner - !$ IF (.FALSE.) & - !$ WRITE(*,*)"process_ps_stack stack size is", param_stack%stack_p,& - !$ omp_get_thread_num(), param_stack%t%t%owner, param_stack%driver,& - !$ param_stack%sid, param_stack%id - ! This has to be reset before the stack may be marked as empty. - stack_size = param_stack%stack_p - param_stack%stack_p = 0 - CALL process_mm_stack(param_stack%parameters,& - param_stack%driver,& - stack_size,& - param_stack%left_data_area, param_stack%right_data_area,& - param_stack%t%t%product_data_area,& - param_stack%t%t%product_data_cuda, param_stack%t%t%has_cuda_c_data,& - param_stack%left_data_cuda, param_stack%right_data_cuda,& - param_stack%state, param_stack%t%t%stack_state_dev,& - param_stack%m, param_stack%n, param_stack%k,& - param_stack%max_m, param_stack%max_n, param_stack%max_k,& - param_stack%defined_mnk,& - param_stack%t%t%c_locks_dev, param_stack%t%t%params_dev,& - param_stack%t%t, & - error=error) - IF (careful_mod) & - CALL dbcsr_error_stop(error_handle, error) - END SUBROUTINE process_ps_stack - ! ***************************************************************************** !> \brief Calls the various drivers that process the stack. @@ -632,15 +78,11 @@ CONTAINS !> \param[in] lastblk Number of blocks in product !> \param[in,out] product_data_area Data for results ! ***************************************************************************** - SUBROUTINE process_mm_stack(params, driver,& + SUBROUTINE process_mm_stack_cpu(params, driver,& stack_size, & left_data_area, right_data_area, product_data_area,& - product_data_card, has_product_data_card,& - a_dev, b_dev,& - state, stack_state_dev,& - m, n, k, max_m, max_n, max_k, defined_mnk,& - c_locks_dev, params_dev, & - target_desc, & + state, m, n, k, max_m, max_n, max_k, defined_mnk,& + stack_id,& error) INTEGER, INTENT(IN) :: stack_size, driver INTEGER, DIMENSION(1:dbcsr_ps_width, & @@ -648,30 +90,21 @@ CONTAINS TYPE(dbcsr_data_obj), INTENT(IN) :: left_data_area, & right_data_area TYPE(dbcsr_data_obj), INTENT(INOUT) :: product_data_area - TYPE(dbcsr_cuda_mem_type), POINTER :: product_data_card - LOGICAL, INTENT(IN) :: has_product_data_card - TYPE(dbcsr_cuda_mem_type), POINTER :: a_dev, b_dev INTEGER, POINTER :: state - TYPE(dbcsr_cuda_mem_type), POINTER :: stack_state_dev INTEGER, INTENT(IN) :: m, n, k, max_m, max_n, max_k LOGICAL, INTENT(IN) :: defined_mnk - TYPE(dbcsr_cuda_mem_type), POINTER :: c_locks_dev, params_dev - TYPE(dbcsr_ps_target_type), POINTER :: target_desc + INTEGER, INTENT(IN) :: stack_id TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'process_mm_stack', & + CHARACTER(len=*), PARAMETER :: routineN = 'process_mm_stack_cpu', & routineP = moduleN//':'//routineN LOGICAL, PARAMETER :: careful = careful_mod, & dbg = .FALSE. REAL, PARAMETER :: resize_factor = 1.618034 - INTEGER :: nregions, sp - LOGICAL, DIMENSION(max_regions) :: which_locks + INTEGER :: sp REAL(KIND=dp) :: rnd -!stack_size), INTENT(IN) :: params -! --------------------------------------------------------------------------- - state = dbcsr_ps_state_working IF (dbg) THEN CALL RANDOM_NUMBER (rnd) @@ -680,7 +113,7 @@ CONTAINS CALL print_gemm_parameters(params(:,1:stack_size)) ENDIF ENDIF - ! + ! Verify stack consistency. Only the upper bound is verified. IF (careful) THEN DO sp = 1, stack_size @@ -701,21 +134,7 @@ CONTAINS "C data out of bounds.", __LINE__, error=error) ENDDO ENDIF - ! - ! Locks the target (data) area if there could be an access - ! conflict there. - ! - !$ IF (mm_thread_workshare .AND. .NOT. driver_is_async (driver)) THEN - !$ CALL dbcsr_ps_target_lock_regions (target_desc,& - !$ stack_size, params,& - !$ target_desc%bit_shift,& - !$ which_locks, nregions,& - !$ error=error) - !$ ENDIF - IF (mm_thread_workshare) THEN - !$OMP FLUSH - ENDIF - + SELECT CASE (driver) CASE (mm_driver_matmul) SELECT CASE (product_data_area%d%data_type) @@ -821,43 +240,15 @@ CONTAINS CALL dbcsr_assert (.FALSE., dbcsr_fatal_level, dbcsr_caller_error,& routineN, "Invalid data type",__LINE__,error) END SELECT - CASE (mm_driver_cuda) - IF (.NOT. has_product_data_card) & - CALL dbcsr_assert (.FALSE.,& - dbcsr_fatal_level, dbcsr_internal_error, routineN,& - "No C data on card is specified.",& - __LINE__, error=error) - CALL cuda_process_mm_stack (params,& - stack_size,& - a_dev, b_dev, product_data_card,& - c_locks_dev,& - params_dev,& - m, n, k, max_m, max_n, max_k, defined_mnk,& - state, stack_state_dev,& - target_desc%owner,& - error=error) CASE default CALL dbcsr_assert (.FALSE., dbcsr_fatal_level, dbcsr_caller_error,& routineN, "Invalid multiplication driver",__LINE__,error) END SELECT - ! - ! These writes have to be ordered. Specifically the state should not - ! be set before the stack has been used and the results written. - IF (mm_thread_workshare) THEN - !$OMP FLUSH - ENDIF + IF (.NOT. driver_is_async (driver)) THEN state = dbcsr_ps_state_empty ENDIF - IF (mm_thread_workshare) THEN - !$OMP FLUSH - ENDIF - !$ IF (mm_thread_workshare .AND. .NOT. driver_is_async (driver)) THEN - !$ CALL dbcsr_ps_target_unlock_regions (target_desc,& - !$ which_locks, nregions,& - !$ error=error) - !$ ENDIF - END SUBROUTINE process_mm_stack + END SUBROUTINE process_mm_stack_cpu ! ***************************************************************************** @@ -870,13 +261,14 @@ CONTAINS !> \param[in,out] c_data Product data !> \param[in,out] error error ! ***************************************************************************** - SUBROUTINE cuda_process_mm_stack(params,& + SUBROUTINE process_mm_stack_cuda(params,& stack_size,& data_a_dev, data_b_dev, data_c_dev,& c_locks,& params_dev,& m, n, k, max_m, max_n, max_k, defined_mnk,& - state, stack_state_dev, owner, & + state, stack_state_dev,& + stack_id,& error) INTEGER, INTENT(IN) :: stack_size INTEGER, & @@ -889,46 +281,45 @@ CONTAINS LOGICAL, INTENT(IN) :: defined_mnk INTEGER, POINTER :: state TYPE(dbcsr_cuda_mem_type), INTENT(IN) :: stack_state_dev - INTEGER, INTENT(IN) :: owner + INTEGER, INTENT(IN) :: stack_id TYPE(dbcsr_error_type), INTENT(INOUT) :: error - CHARACTER(len=*), PARAMETER :: routineN = 'cuda_process_mm_stack', & + CHARACTER(len=*), PARAMETER :: routineN = 'process_mm_stack_cuda', & routineP = moduleN//':'//routineN INTEGER, PARAMETER :: flops_to_sort = 2*13*13*13 INTEGER :: error_handle, error_handle2, & - i, k_max, m_max, n_max, stream + i, ithread, k_max, m_max, & + n_max, nthreads, stream INTEGER, DIMENSION(:), POINTER :: params_p INTEGER, DIMENSION(stack_size) :: c_sort, c_sort_ind INTEGER, & DIMENSION(dbcsr_ps_width, stack_size) :: params_sort, params_tmp -! sort for matrices 13x13 and larger, this parameter needs tuning -! --------------------------------------------------------------------------- + nthreads = 1; ithread = 0 + !$ nthreads = OMP_GET_NUM_THREADS () ; ithread = OMP_GET_THREAD_NUM () IF (stack_size .EQ. 0) THEN - !$OMP FLUSH state = dbcsr_ps_state_empty - !$OMP FLUSH WRITE(*,*)routineN//" Stack size is 0" - !$ write(*,*)"from thread", omp_get_thread_num() RETURN ENDIF - stream = owner+1 - !$ IF (.FALSE.) & - !$ WRITE(*,*)routineN//" Stack size is", stack_size, omp_get_thread_num() - ! IF (careful_mod) & - CALL dbcsr_error_set (routineN, error_handle, error) - + + ! ithread is 0-based, stack_id is 1-based, stream should be 1-based + stream = ithread + nthreads*(stack_id-1) + 1 + CALL dbcsr_error_set (routineN, error_handle, error) + params_p => params IF (m .GT. 0) THEN ; m_max = m ; ELSE ; m_max = -max_m ; ENDIF IF (n .GT. 0) THEN ; n_max = n ; ELSE ; n_max = -max_n ; ENDIF IF (k .GT. 0) THEN ; k_max = k ; ELSE ; k_max = -max_k ; ENDIF - !======================================== + + !=========================================================================== ! sort the stack. Since this costs CPU time, only a good idea if the CPUs ! are not too busy, or GPU gain is very large CALL dbcsr_error_set (routineN//"_sort", error_handle2, error) - IF (2*m*n*k>=flops_to_sort .AND. stack_size .GT. 1) THEN + !TODO: now we are allways sorting + !IF (2*m*n*k>=flops_to_sort .AND. stack_size .GT. 1) THEN params_tmp = RESHAPE(params, (/dbcsr_ps_width, stack_size/)) ! sort by the C-blocks c_sort = params_tmp(6,:) @@ -937,34 +328,31 @@ CONTAINS params_sort(:, i)=params_tmp(:, c_sort_ind(i)) END DO params = RESHAPE(params_sort, (/dbcsr_ps_width*stack_size/)) - ENDIF + !ENDIF CALL dbcsr_error_stop (error_handle2, error) - !======================================== + !=========================================================================== + + CALL dbcsr_cuda_cp_host_to_dev (params_p,& params_dev%d_i, dbcsr_ps_width*stack_size,& async=.TRUE., stream=stream,& error=error) - + ! Schedule the resetting of the state of this stack as soon as the ! parameter upload finishes. N.B. This must be the last change to ! the stack: its stack_p must be set to 0 and its data must be ! used before the state is set to dbcsr_ps_state_empty. CALL dbcsr_cuda_cp_dev_to_host (stack_state_dev%d_i, state,& async=.TRUE., stream=stream, error=error) - - !--- !$OMP CRITICAL (crit_cuda) - !$ IF (mm_thread_workshare) CALL OMP_SET_LOCK (accel_lock) + + !TODO: dbcsr_ps_width is a constant, shouldn't need to pass it as argument CALL dbcsr_cuda_do_mm_stack (params_dev%d_i, stack_size, dbcsr_ps_width,& data_a_dev, data_b_dev, data_c_dev,& c_locks%d_i, ABS(m_max), ABS(n_max), ABS(k_max), defined_mnk,& stream=stream, error=error) - !$ IF (mm_thread_workshare) CALL OMP_UNSET_LOCK (accel_lock) - !--- !$OMP END CRITICAL (crit_cuda) - IF (.FALSE.) CALL dbcsr_cuda_device_sync (error=error) -! IF (careful_mod) & - CALL dbcsr_error_stop (error_handle, error) - END SUBROUTINE cuda_process_mm_stack + CALL dbcsr_error_stop (error_handle, error) + END SUBROUTINE process_mm_stack_cuda diff --git a/src/dbcsr_lib/dbcsr_mm_types.F b/src/dbcsr_lib/dbcsr_mm_types.F index dd2e1c3849..10169b9845 100644 --- a/src/dbcsr_lib/dbcsr_mm_types.F +++ b/src/dbcsr_lib/dbcsr_mm_types.F @@ -18,9 +18,8 @@ MODULE dbcsr_mm_types int_8,& real_8,& sp - USE dbcsr_pq_types, ONLY: dbcsr_pq_type,& - dbcsr_ps_set_type - USE dbcsr_types, ONLY: dbcsr_work_type + USE dbcsr_types, ONLY: dbcsr_data_obj,& + dbcsr_work_type IMPLICIT NONE @@ -28,7 +27,23 @@ MODULE dbcsr_mm_types CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbcsr_mm_types' - PUBLIC :: carrier_type, hash_table_type, ele_type + PUBLIC :: multrec_carrier_type, csr_carrier_type + PUBLIC :: driver_carrier_type, stack_descriptor_type + PUBLIC :: hash_table_type, ele_type + + INTEGER, PARAMETER, PUBLIC :: dbcsr_ps_state_empty = 42424242 + INTEGER, PARAMETER, PUBLIC :: dbcsr_ps_state_working = 1234567890 + + ! Definitions for the members of a parameter stack. + INTEGER, PARAMETER, PUBLIC :: dbcsr_ps_width = 7 + INTEGER, PARAMETER, PUBLIC :: p_m = 1 + INTEGER, PARAMETER, PUBLIC :: p_n = 2 + INTEGER, PARAMETER, PUBLIC :: p_k = 3 + INTEGER, PARAMETER, PUBLIC :: p_a_first = 4 + INTEGER, PARAMETER, PUBLIC :: p_b_first = 5 + INTEGER, PARAMETER, PUBLIC :: p_c_first = 6 + INTEGER, PARAMETER, PUBLIC :: p_c_blk = 7 + ! ***************************************************************************** !> \brief Types needed for the hashtable. @@ -37,7 +52,7 @@ MODULE dbcsr_mm_types INTEGER :: c=0 INTEGER :: p=0 END TYPE ele_type - + TYPE hash_table_type TYPE(ele_type), DIMENSION(:), POINTER :: table INTEGER :: nele=0 @@ -45,15 +60,58 @@ MODULE dbcsr_mm_types INTEGER :: prime=0 END TYPE hash_table_type - + +! ***************************************************************************** +!> +! ***************************************************************************** + TYPE stack_descriptor_type + INTEGER :: m, n, k, max_m ,max_n, max_k + INTEGER :: total_entries + LOGICAL :: defined_mnk + END TYPE stack_descriptor_type + + +! ***************************************************************************** +!> +! ***************************************************************************** + TYPE driver_carrier_type + ! for cpu based drivers + TYPE(dbcsr_data_obj) :: left_data_area, right_data_area + TYPE(dbcsr_work_type), POINTER :: product_wm + ! for the cuda driver + END TYPE driver_carrier_type + + +! ***************************************************************************** +!> +! ***************************************************************************** + TYPE csr_carrier_type + TYPE(hash_table_type), DIMENSION(:), POINTER :: c_hashes + INTEGER :: nm_stacks, nn_stacks, nk_stacks + INTEGER(KIND=int_4), DIMENSION(:), POINTER :: m_size_maps,& + n_size_maps,& + k_size_maps + INTEGER :: max_m, max_n, max_k + INTEGER :: m_size_maps_size,& + n_size_maps_size,& + k_size_maps_size + + INTEGER(KIND=int_1), DIMENSION(:,:,:), POINTER :: stack_map + + INTEGER, DIMENSION(:,:,:,:), POINTER :: stackgrid_data + INTEGER, DIMENSION(:,:), POINTER :: stackgrid_fillcount + INTEGER, DIMENSION(:,:), POINTER :: stackgrid_state + TYPE(stack_descriptor_type), DIMENSION(:), POINTER :: stackrow_descr + TYPE(driver_carrier_type) :: drv_carrier + END TYPE csr_carrier_type + + ! ***************************************************************************** !> \brief Used to carry data among the various calls. Each thread has !> its own private copy. -!> \var id Unique ID of each carrier_type instance !> \var c_has_symmetry The product matrix has symmetry !> \var keep_sparsity Sparsity of C matrix should be kept !> \var use_eps Use on-the-fly filtering -!> \var param_sets Set of parameter stacks !> \var local_indexing The A and B matrix indices and C matrix work indices !> are not global but local to process rows and columns !> \var m_sizes Block sizes of A and C matrix rows, indexed locally @@ -92,7 +150,6 @@ MODULE dbcsr_mm_types !> \var nk_stacks The number of most common k blocks sizes. !> \var stack_map Map from most common (n,k,m) block sizes to a stack !> number within a stack group. -!> \var default_stack Stack to use when stack members do not have common !> m, n, and k sizes. !> \var row_max_epss Maximum eps to be used for one row. !> \var a_norms Norms of A matrix blocks. @@ -105,38 +162,18 @@ MODULE dbcsr_mm_types !> \var original_lastblk Number of work matrix blocks before addition !> \var flop flop count ! ***************************************************************************** - TYPE carrier_type - INTEGER :: id + TYPE multrec_carrier_type LOGICAL :: c_has_symmetry, keep_sparsity, use_eps LOGICAL :: local_indexing - TYPE(hash_table_type), DIMENSION(:), POINTER :: c_hashes - TYPE(dbcsr_pq_type), POINTER :: queue - TYPE(dbcsr_ps_set_type) :: param_sets INTEGER, DIMENSION(:), POINTER :: m_sizes, n_sizes, k_sizes INTEGER, DIMENSION(:), POINTER :: c_local_rows, c_local_cols, k_locals,& c_global_rows, c_global_cols - INTEGER :: max_m, max_n, max_k - INTEGER(KIND=int_4), DIMENSION(:), POINTER :: m_size_maps,& - n_size_maps,& - k_size_maps - INTEGER :: m_size_maps_size,& - n_size_maps_size,& - k_size_maps_size - INTEGER :: nm_stacks, nn_stacks, nk_stacks - INTEGER(KIND=int_1), DIMENSION(:,:,:), POINTER :: stack_map - INTEGER :: default_stack + REAL(KIND=sp), DIMENSION(:), POINTER :: row_max_epss, a_norms, b_norms REAL(KIND=real_8) :: eps - TYPE(dbcsr_work_type) :: my_wm - INTEGER :: lastblk, datasize INTEGER :: original_lastblk INTEGER(kind=int_8) :: flop - INTEGER, DIMENSION(:,:), POINTER :: right_data_sr, right_data_rr,& - left_data_sr, left_data_rr,& - right_index_sr, right_index_rr,& - left_index_sr, left_index_rr - END TYPE carrier_type + TYPE(csr_carrier_type) :: csr_carrier + END TYPE multrec_carrier_type - - END MODULE dbcsr_mm_types diff --git a/src/dbcsr_lib/dbcsr_operations.F b/src/dbcsr_lib/dbcsr_operations.F index 39e2096004..39d93f6131 100644 --- a/src/dbcsr_lib/dbcsr_operations.F +++ b/src/dbcsr_lib/dbcsr_operations.F @@ -35,16 +35,11 @@ MODULE dbcsr_operations dbcsr_data_clear,& get_block2d_diagonal,& set_block2d_diagonal - USE dbcsr_config, ONLY: & - dbcsr_get_conf_mm_stacksize, dbcsr_get_conf_nstacks, dbcsr_init_conf, & - has_cuda, is_configured, mm_async, mm_driver, mm_driver_cuda, & - mm_driver_plasma - USE dbcsr_cuda_device, ONLY: dbcsr_cuda_get_n_devices,& - dbcsr_cuda_init - USE dbcsr_cuda_memory, ONLY: dbcsr_cuda_dev_mem_alloc,& - dbcsr_cuda_dev_mem_dealloc - USE dbcsr_cuda_methods, ONLY: dbcsr_cuda_dev_mem_setup - USE dbcsr_cuda_types, ONLY: dbcsr_cuda_mem_type + USE dbcsr_config, ONLY: dbcsr_init_conf,& + is_configured,& + mm_async,& + mm_driver,& + mm_driver_plasma USE dbcsr_data_methods, ONLY: & dbcsr_data_clear_pointer, dbcsr_data_ensure_size, dbcsr_data_get_size, & dbcsr_data_get_type, dbcsr_data_init, dbcsr_data_new, & @@ -80,7 +75,6 @@ MODULE dbcsr_operations USE dbcsr_message_passing, ONLY: dmp_max,& mp_allgather,& mp_bcast,& - mp_environ,& mp_recv,& mp_send,& mp_sum @@ -105,13 +99,13 @@ MODULE dbcsr_operations dbcsr_nblkrows_total, dbcsr_nfullcols_total, dbcsr_nfullrows_total, & dbcsr_release, dbcsr_release_locals, dbcsr_row_block_offsets, & dbcsr_row_block_sizes, dbcsr_switch_data_area, dbcsr_valid_index - USE dbcsr_mm_cannon, ONLY: dbcsr_mult_m_e_e + USE dbcsr_mm_cannon, ONLY: dbcsr_mm_cannon_lib_finalize,& + dbcsr_mm_cannon_lib_init,& + dbcsr_mm_cannon_multiply USE dbcsr_mp_operations, ONLY: dbcsr_recv_any,& dbcsr_send_any USE dbcsr_plasma_interface, ONLY: dbcsr_plasma_finalize,& dbcsr_plasma_init - USE dbcsr_pq_methods, ONLY: dbcsr_ps_set_finalize,& - dbcsr_ps_set_init USE dbcsr_ptr_util, ONLY: ensure_array_size,& pointer_view USE dbcsr_toollib, ONLY: ceil_log2,& @@ -126,15 +120,14 @@ MODULE dbcsr_operations USE dbcsr_types, ONLY: & dbcsr_2d_array_type, dbcsr_conjugate_transpose, dbcsr_data_obj, & dbcsr_distribution_obj, dbcsr_filter_frobenius, & - dbcsr_imagedistribution_obj, dbcsr_iterator, & - dbcsr_memory_CUDA_host_pinned, dbcsr_memory_MPI, dbcsr_memory_default, & - dbcsr_mp_obj, dbcsr_no_transpose, dbcsr_norm_column, & - dbcsr_norm_frobenius, dbcsr_norm_gershgorin, dbcsr_norm_maxabsnorm, & - dbcsr_obj, dbcsr_repl_col, dbcsr_repl_full, dbcsr_repl_none, & - dbcsr_repl_row, dbcsr_scalar_type, dbcsr_transpose, dbcsr_type, & - dbcsr_type_antisymmetric, dbcsr_type_complex_4, dbcsr_type_complex_8, & - dbcsr_type_no_symmetry, dbcsr_type_real_4, dbcsr_type_real_8, & - dbcsr_type_symmetric + dbcsr_imagedistribution_obj, dbcsr_iterator, dbcsr_memory_MPI, & + dbcsr_memory_default, dbcsr_mp_obj, dbcsr_no_transpose, & + dbcsr_norm_column, dbcsr_norm_frobenius, dbcsr_norm_gershgorin, & + dbcsr_norm_maxabsnorm, dbcsr_obj, dbcsr_repl_col, dbcsr_repl_full, & + dbcsr_repl_none, dbcsr_repl_row, dbcsr_scalar_type, dbcsr_transpose, & + dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_complex_4, & + dbcsr_type_complex_8, dbcsr_type_no_symmetry, dbcsr_type_real_4, & + dbcsr_type_real_8, dbcsr_type_symmetric USE dbcsr_util, ONLY: dbcsr_checksum,& dbcsr_verify_matrix,& find_block_of_element @@ -142,8 +135,6 @@ MODULE dbcsr_operations dbcsr_create,& dbcsr_finalize,& dbcsr_work_create - USE ma_affinity, ONLY: ma_set_gpu_affinity - USE machine_architecture_types, ONLY: has_ma !$ USE OMP_LIB @@ -158,7 +149,7 @@ MODULE dbcsr_operations PUBLIC :: dbcsr_init_lib, dbcsr_finalize_lib PUBLIC :: dbcsr_multiply,& - dbcsr_mult_m_e_e, dbcsr_trace, dbcsr_add_on_diag,& + dbcsr_trace, dbcsr_add_on_diag,& dbcsr_set, dbcsr_scale, dbcsr_scale_mat, dbcsr_add, dbcsr_copy,& dbcsr_copy_submatrix, dbcsr_copy_into_existing,& dbcsr_get_diag, dbcsr_set_diag, & @@ -378,7 +369,6 @@ CONTAINS old_product_col_blk_sizes, old_product_row_blk_offsets, & old_product_row_blk_sizes TYPE(dbcsr_2d_array_type), POINTER :: m2s_left, m2s_right - TYPE(dbcsr_cuda_mem_type) :: a_tmp TYPE(dbcsr_distribution_obj) :: dense_product_distribution, & old_product_distribution TYPE(dbcsr_imagedistribution_obj) :: dense_rdist_left, & @@ -388,19 +378,6 @@ CONTAINS matrix_left, matrix_right, matrix_tmp, product_matrix TYPE(dbcsr_scalar_type) :: eps_any -! --------------------------------------------------------------------------- -! Pre-init card for nicer time acconting. - - IF (has_cuda) THEN - IF(mm_driver .NE. mm_driver_cuda) CALL dbcsr_ps_set_finalize(error=error) - ENDIF - - IF (mm_driver .EQ. mm_driver_cuda) THEN - CALL dbcsr_cuda_dev_mem_setup (a_tmp, dbcsr_type_real_8) - CALL dbcsr_cuda_dev_mem_alloc(a_tmp, 1, error=error) - CALL dbcsr_cuda_dev_mem_dealloc(a_tmp, error=error) - ENDIF - ! CALL dbcsr_error_set(routineN, error_handler, error) ! ! check parameters @@ -963,7 +940,7 @@ CONTAINS CALL dbcsr_access_flush (product_matrix, error=error) ! my_flop = 0 - CALL dbcsr_mult_m_e_e (m2s_left, m2s_right, product_matrix,& + CALL dbcsr_mm_cannon_multiply(m2s_left, m2s_right, product_matrix,& retain_sparsity=retain_sparsity,& filter_eps=filter_eps, error=error,& flop=my_flop) @@ -4478,12 +4455,12 @@ CONTAINS CHARACTER(len=*), PARAMETER :: routineN = 'dbcsr_init_lib', & routineP = moduleN//':'//routineN - INTEGER :: error_handle, group_size, mem_type, mynode, n_stack_buffers, & - n_stack_mem_regions, ngpus, nstacks, numnode, stack_size - INTEGER, DIMENSION(3) :: nxstacks - TYPE(dbcsr_error_type) :: t_error + INTEGER :: error_handle +!n_stack_buffers,mem_type, n_stack_mem_regions, stack_size, nstacks,& +!INTEGER, DIMENSION(3) :: nxstacks ! --------------------------------------------------------------------------- +!TODO: problem: init/finalize are called by cp2k_runs AND f77_interface IF (is_configured) RETURN CALL dbcsr_error_set(routineN, error_handle, error) @@ -4504,45 +4481,13 @@ CONTAINS dbcsr_fatal_level, dbcsr_internal_error, routineN,& "Incorrect assumption of a 64-bit integer size!",& __LINE__, error=error) - ! + CALL dbcsr_init_conf (error) - ! - CALL mp_environ (numnode, mynode, group) -#if defined (__DBCSR_CUDA) - IF (has_cuda) THEN - ngpus = dbcsr_cuda_get_n_devices (error) - mem_type = dbcsr_memory_CUDA_host_pinned - CALL dbcsr_get_conf_nstacks (nxstacks, n_stack_buffers, n_stack_mem_regions,& - error) + !$omp parallel default(none) shared(error) + CALL dbcsr_mm_cannon_lib_init(error) + !$omp end parallel - nstacks = nxstacks(1) * nxstacks(2) * nxstacks(3) + 1 - stack_size = dbcsr_get_conf_mm_stacksize()*n_stack_buffers*nstacks - group_size = n_stack_buffers*nstacks - - - !$OMP PARALLEL default (none), & - !$OMP private (t_error) & - !$OMP shared (mynode, ngpus, error, & - !$OMP group_size, n_stack_mem_regions,stack_size) - - ! use a critical section to allow for threads initializing static - ! variables without races - !$OMP CRITICAL - t_error = error - IF (has_ma) THEN - CALL dbcsr_cuda_init (card_num=ma_set_gpu_affinity(mynode), error=error) - ELSE - CALL dbcsr_cuda_init (card_num=MOD(mynode, ngpus), error=error) - ENDIF - !$OMP END CRITICAL - - !allocate host memory - CALL dbcsr_ps_set_init(group_size, n_stack_mem_regions,stack_size,error=error) - !$OMP END PARALLEL - ENDIF -#endif - ! is_configured = .TRUE. CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_init_lib @@ -4562,12 +4507,20 @@ CONTAINS INTEGER :: error_handle - CALL dbcsr_ps_set_finalize(error=error) +!TODO: problem: init/finalize are called by cp2k_runs AND f77_interface + + IF (.NOT. is_configured) RETURN CALL dbcsr_error_set(routineN, error_handle, error) + + !$omp parallel default(none) shared(error) + CALL dbcsr_mm_cannon_lib_finalize(error) + !$omp end parallel + + is_configured = .FALSE. CALL dbcsr_error_stop (error_handle, error) END SUBROUTINE dbcsr_finalize_lib - + ! ***************************************************************************** !> \brief Adds blocks to a matrix diff --git a/src/dbcsr_lib/dbcsr_ptr_util.F b/src/dbcsr_lib/dbcsr_ptr_util.F index 8ef6f25486..7cc0eb6b92 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util.F +++ b/src/dbcsr_lib/dbcsr_ptr_util.F @@ -302,7 +302,7 @@ CONTAINS CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -344,7 +344,7 @@ CONTAINS CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/dbcsr_lib/dbcsr_ptr_util__nametype1_.template b/src/dbcsr_lib/dbcsr_ptr_util__nametype1_.template index 4a02557c8d..0c5f9aa475 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util__nametype1_.template +++ b/src/dbcsr_lib/dbcsr_ptr_util__nametype1_.template @@ -200,7 +200,7 @@ CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -240,7 +240,7 @@ CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/dbcsr_lib/dbcsr_ptr_util_c.F b/src/dbcsr_lib/dbcsr_ptr_util_c.F index 2262dc821b..dbf94f1384 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util_c.F +++ b/src/dbcsr_lib/dbcsr_ptr_util_c.F @@ -200,7 +200,7 @@ CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -240,7 +240,7 @@ CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/dbcsr_lib/dbcsr_ptr_util_d.F b/src/dbcsr_lib/dbcsr_ptr_util_d.F index 1ef1d5391b..691f06c660 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util_d.F +++ b/src/dbcsr_lib/dbcsr_ptr_util_d.F @@ -200,7 +200,7 @@ CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -240,7 +240,7 @@ CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/dbcsr_lib/dbcsr_ptr_util_s.F b/src/dbcsr_lib/dbcsr_ptr_util_s.F index 11437d063b..6801bcbafe 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util_s.F +++ b/src/dbcsr_lib/dbcsr_ptr_util_s.F @@ -200,7 +200,7 @@ CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -240,7 +240,7 @@ CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/dbcsr_lib/dbcsr_ptr_util_z.F b/src/dbcsr_lib/dbcsr_ptr_util_z.F index e3f5c90a18..225bfac786 100644 --- a/src/dbcsr_lib/dbcsr_ptr_util_z.F +++ b/src/dbcsr_lib/dbcsr_ptr_util_z.F @@ -200,7 +200,7 @@ CASE (dbcsr_memory_MPI) CALL mp_allocate(mem, n, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_alloc(mem, n, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_alloc(mem, n, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& @@ -240,7 +240,7 @@ CASE (dbcsr_memory_MPI) CALL mp_deallocate(mem, stat=stat) CASE (dbcsr_memory_CUDA_host_pinned) - CALL dbcsr_cuda_host_mem_dealloc(mem, stat=stat, error=error) + CALL dbcsr_cuda_host_mem_dealloc(mem, error=error) CASE default CALL dbcsr_assert (.FALSE.,& dbcsr_fatal_level, dbcsr_unimplemented_error_nr, routineN,& diff --git a/src/input_cp2k.F b/src/input_cp2k.F index 04bb636738..0724a65012 100644 --- a/src/input_cp2k.F +++ b/src/input_cp2k.F @@ -28,7 +28,7 @@ MODULE input_cp2k dbcsr_get_conf_use_comm_thread, has_blas, has_cuda, has_plasma, & has_smm_gemm, mm_driver_blas, mm_driver_cuda, mm_driver_matmul, & mm_driver_plasma, mm_driver_smm, mm_name_blas, mm_name_cuda, & - mm_name_matmul, mm_name_plasma, mm_name_smm, mm_thread_workshare + mm_name_matmul, mm_name_plasma, mm_name_smm USE dbcsr_error_handling USE dbcsr_types, ONLY: dbcsr_type_complex_4,& dbcsr_type_complex_8,& @@ -802,7 +802,7 @@ CONTAINS CHARACTER(len=64) :: a_blas, a_cuda, a_plasma, & a_smm - INTEGER :: n_buffers, n_mem_regions + INTEGER :: n_buffers INTEGER, DIMENSION(3) :: nstacks LOGICAL :: failure TYPE(dbcsr_error_type) :: dbcsr_error @@ -904,7 +904,7 @@ CONTAINS CALL section_add_keyword(section,keyword,error=error) CALL keyword_release(keyword,error=error) ! - CALL dbcsr_get_conf_nstacks (nstacks, n_buffers, n_mem_regions, dbcsr_error) + CALL dbcsr_get_conf_nstacks (nstacks, n_buffers, dbcsr_error) CALL keyword_create(keyword, name="n_size_mnk_stacks",& description="Number of stacks to use for distinct atomic sizes" & // " (e.g., 2 for a system of mostly waters).",& @@ -919,36 +919,7 @@ CONTAINS default_i_val=n_buffers,error=error) CALL section_add_keyword(section,keyword,error=error) CALL keyword_release(keyword,error=error) - CALL keyword_create(keyword, name="n_stack_memory_regions",& - description="Number of memory regions to use for stacks" & - // " (e.g., number of GPU cards per MPI process)",& - usage="n_stack_memory_regions 2",& - default_i_val=n_mem_regions,error=error) - CALL section_add_keyword(section,keyword,error=error) - CALL keyword_release(keyword,error=error) - ! - CALL keyword_create(keyword, name="mm_thread_workshare",& - description="Share matrix multiplication work between multiple threads",& - usage="mm_thread_workshare T",& - variants=(/"MM_WORKSHARE"/),& - default_l_val=mm_thread_workshare,error=error) - CALL section_add_keyword(section,keyword,error=error) - CALL keyword_release(keyword,error=error) - ! - CALL keyword_create(keyword, name="detailed_timing",& - description="Output multiplication timing (development)",& - usage="detailed_timing T",& - default_l_val=.FALSE.,error=error) - CALL section_add_keyword(section,keyword,error=error) - CALL keyword_release(keyword,error=error) - ! - CALL keyword_create(keyword, name="kernel_timing",& - description="Time multiplication kernel (development)",& - usage="kernel_timing T",& - default_l_val=.FALSE.,error=error) - CALL section_add_keyword(section,keyword,error=error) - CALL keyword_release(keyword,error=error) - ! + CALL keyword_create(keyword, name="use_comm_thread",& description="During multiplication, use a thread to periodically poll" & // " MPI to progress outstanding message completions. This is" & diff --git a/tests/LIBTEST/dbcsr_multistack.inp b/tests/LIBTEST/dbcsr_multistack.inp index 936af3d16b..f104d6e6ba 100644 --- a/tests/LIBTEST/dbcsr_multistack.inp +++ b/tests/LIBTEST/dbcsr_multistack.inp @@ -8,7 +8,6 @@ &DBCSR n_size_mnk_stacks 2 n_stack_buffers 4 - n_stack_memory_regions 5 &END DBCSR &END GLOBAL &TEST