program x3d2_memcheck !! Standalone GPU memory estimator for an x3d2 .x3d input file. !! --static The formula estimate only. !! (no flag) The formula estimate, then an FFT plan probe on the whole !! grid. !! --build The above, then a real case build and one substep on 1 GPU, !! measured with cudaMemGetInfo, and a CHECK line against the !! estimate. !! The probe gives the CUDA context and the NVSHMEM heap of the GPU in !! use. The GPU-aware IO staging buffer is added by formula. !! Usage: x3d2-memcheck <input.x3d> [--static | --build [--extensive <n>]] use mpi use m_common, only: i8 use m_logger, only: abort_run, log_info use m_memory_estimate, only: output_field_active, peak_fields_lookup use m_memcheck_context, only: memcheck_ctx_t, parse_args, read_config, & classify_bc, resolve_gpu_io_mode use m_memcheck_estimate, only: to_gib use m_memcheck_report, only: report use m_memcheck_build, only: run_build_mode implicit none type(memcheck_ctx_t) :: ctx integer :: ierr, nproc logical :: device_ok character(len=128) :: device_msg call MPI_Init(ierr) call MPI_Comm_rank(MPI_COMM_WORLD, ctx%irank, ierr) call MPI_Comm_size(MPI_COMM_WORLD, nproc, ierr) if (nproc /= 1) call abort_run( & 'x3d2-memcheck: run single-rank (mpirun -n 1).', collective=.true.) call ctx%device%init(device_ok, device_msg) if (.not. device_ok) then call log_info(trim(device_msg)) call no_device_exit() end if call parse_args(ctx) call read_config(ctx) call resolve_gpu_io_mode(ctx) call classify_bc(ctx) call query_card_gib() ctx%peak_fields = peak_fields_lookup( & trim(ctx%domain_cfg%flow_case_name), & ctx%solver_cfg%time_intg, & ctx%solver_cfg%n_species, & trim(ctx%les_cfg%model) /= 'none', & ctx%solver_cfg%ibm_on, & output_field_active(ctx%checkpoint_cfg, 'vorticity'), & output_field_active(ctx%checkpoint_cfg, 'qcriterion'), & ctx%solver_cfg%lowmem_transeq) ! Exception to the solver rule: the CUDA solver accepts 110 on ! nproc > 1 through cuFFTMp, but x3d2-memcheck keeps 110 single GPU until ! the multi-rank buffers of #417 are in the estimate. Sharing the solver ! rule now would print supported rows with under-estimated figures. ctx%multi_gpu_supported = .not. (ctx%bc_is_010 .or. ctx%bc_is_110) call report(ctx) if (trim(ctx%run_mode) == 'BUILD') call run_build_mode(ctx) call MPI_Finalize(ierr) ! Exit code: 0 FITS, 1 BORDERLINE, 2 DOES_NOT_FIT or UNSUPPORTED. select case (trim(ctx%final_verdict)) case ('FITS') call exit(0) case ('BORDERLINE') call exit(1) case default call exit(2) end select contains subroutine no_device_exit() !! Shuts MPI down, then stops. integer :: ierr_finalize call MPI_Finalize(ierr_finalize) call abort_run('x3d2-memcheck: no usable CUDA device', collective=.true.) end subroutine no_device_exit subroutine query_card_gib() integer(i8) :: free_b, total_b call ctx%device%mem_info(total_b, free_b) ctx%card_gib = to_gib(total_b) ctx%card_free_gib = to_gib(free_b) end subroutine query_card_gib end program x3d2_memcheck