Skip to content

Commit b32e14b

Browse files
author
jojo
committed
restart davidson subspace according to available memory or user specify a value; move RisBase to top of ris.py clear for reading
1 parent bf921e4 commit b32e14b

File tree

3 files changed

+1504
-1475
lines changed

3 files changed

+1504
-1475
lines changed

gpu4pyscf/tdscf/_krylov_tools.py

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020

2121
from gpu4pyscf.tdscf import math_helper
22-
from gpu4pyscf.tdscf.math_helper import gpu_mem_info, release_memory
22+
from gpu4pyscf.tdscf.math_helper import gpu_mem_info, release_memory, get_avail_gpumem, get_avail_cpumem
2323
from gpu4pyscf.lib.cupy_helper import asarray as cuasarray
2424

2525

@@ -260,8 +260,7 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
260260
initguess_fn=None, precond_fn=None, rhs=None,
261261
omega_shift=None, n_states=20,conv_tol=1e-5,
262262
max_iter=35, extra_init=8, gs_initial=False, gram_schmidt=True,
263-
restart_iter=None,
264-
single=False, in_ram=False, print_eigeneV_along=False,
263+
restart_subspace=None, single=False, in_ram=False,
265264
verbose=logger.NOTE):
266265
'''
267266
This solver is used to solve the following problems:
@@ -332,17 +331,16 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
332331
maximum iterations
333332
extra_init: int
334333
extra number of states to be initialized
335-
restart_iter: int or None
336-
restart the Krylov solver periodically after this iteration. Default None, no restart.
334+
restart_subspace: int or None
335+
restart the Krylov solver periodically if the subspace size is larger than this value.
336+
Default None, no restart.
337337
gs_initial: bool
338338
apply gram_schmidt procedure on the initial guess,
339339
only in the case of gram_schmidt = True, but given wired initial guess
340340
gram_schmidt: bool
341341
use Gram-Schmidt orthogonalization
342342
single: bool
343343
use single precision
344-
print_eigeneV_along:
345-
print energies in each iteration
346344
verbose: logger.Logger
347345
logger object
348346
@@ -404,13 +402,25 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
404402
# record the initial size of the Krylov subspace
405403
n_init = size_new
406404

407-
if restart_iter is not None and restart_iter > 0:
408-
max_N_mv = size_new + restart_iter * n_states
405+
log.info(f'single trial vector X_ia size: {A_size*hdiag.itemsize/1024**2:.2f} MB')
406+
if restart_subspace is None:
407+
''' calculate the maximum number of vectors allowed by the memory'''
408+
if in_ram:
409+
available_mem = get_avail_cpumem()
410+
else:
411+
available_mem = get_avail_gpumem()
412+
413+
restart_subspace = int((available_mem * 0.9) // (2*A_size*hdiag.itemsize))
414+
log.info(f'the maximum number of vectors allowed by the memory is {restart_subspace}')
409415
else:
410-
max_N_mv = size_new + max_iter * n_states
416+
log.info(f'user specified the maximum number of vectors is {restart_subspace}')
417+
418+
max_N_mv = min(size_new + max_iter * n_states, restart_subspace)
419+
log.info(f'the maximum number of vectors in V_holder and W_holder is {max_N_mv}')
411420

412421
# Initialize arrays
413422
V_holder_mem = max_N_mv*A_size*hdiag.itemsize/1024**3
423+
414424
if in_ram:
415425
rss = current_memory()[0] / 1024 # current memory usage in GB
416426
log.info(f'the maximum CPU memory usage throughout the Krylov solver is around {2*V_holder_mem + rss:.2f} GB')
@@ -566,6 +576,7 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
566576
log.info(gpu_mem_info(' MVP stored in W_holder'))
567577

568578
_time_add(log, t_mvp, t0)
579+
log.timer(f' MVP total cost', *t0)
569580

570581
''' Project into Krylov subspace '''
571582
t0 = log.init_timer()
@@ -607,8 +618,7 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
607618

608619
omega = omega[:n_states]
609620
x = x[:, :n_states]
610-
if print_eigeneV_along:
611-
log.info(f' Energies (eV): {[round(e,3) for e in (omega*HARTREE2EV).tolist()]}')
621+
log.info(f' Energies (eV): {[round(e,3) for e in (omega*HARTREE2EV).tolist()]}')
612622

613623
elif problem_type == 'linear':
614624
x = cp.linalg.solve(sub_A, sub_rhs)
@@ -690,7 +700,7 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
690700
data = {
691701
"con_tol": conv_tol,
692702
"max_iter": max_iter,
693-
"restart_iter": restart_iter,
703+
"restart_subspace": restart_subspace,
694704
"in_ram": in_ram,
695705
"problem_type": problem_type,
696706
"n_states": n_states,
@@ -719,9 +729,12 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
719729

720730
else:
721731

722-
if restart_iter is not None and (ii+1) % restart_iter == 0:
723-
log.info(f' !!! restarting Krylov solver at iteration {ii+1} (every {restart_iter} iterations)')
732+
unconverged_idx = cp.where(r_norms.ravel() > conv_tol)[0]
733+
log.info(f' number of unconverged states: {unconverged_idx.size}')
734+
724735

736+
if restart_subspace is not None and size_new + unconverged_idx.size > restart_subspace:
737+
log.info(f' !!! restart subspace (subspace {size_new+unconverged_idx.size} > {restart_subspace})')
725738
''' fill N_state solution into the V_holder, but keep the initial guess vectors
726739
to fully remove the numerical noise, W_holder is also restarted
727740
'''
@@ -742,9 +755,6 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
742755
# residual_unconv = residual[index_bool, :] with boolean indexing creates a copy, which costs extra memory
743756
# instead, manually move the unconverged residual vectors forehead, use residual[:unconverged_idx.size, :] to save memory
744757

745-
unconverged_idx = cp.where(r_norms.ravel() > conv_tol)[0]
746-
log.info(f' number of unconverged states: {unconverged_idx.size}')
747-
748758
pos = 0
749759
for idx in unconverged_idx:
750760
if idx != pos:
@@ -769,12 +779,11 @@ def krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue',
769779
t0 = log.init_timer()
770780
log.info(gpu_mem_info(' ▸ Preconditioning ends'))
771781

772-
# _V_holder, size_new = fill_holder(V_holder, size_old, X_new)
773-
log.info(' putting new guesses into the holder')
782+
log.info(' putting new guesses into the holder')
774783

775784
size_old = size_new
776785
size_new = fill_holder(V_holder, size_old, X_new)
777-
log.timer(' new guesses put into the holder', *t0)
786+
log.timer(' new guesses put into the holder', *t0)
778787

779788
del X_new, residual
780789
release_memory()
@@ -826,8 +835,8 @@ def nested_krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue'
826835
init_mvp=None, precond_mvp=None, extra_init=3, extra_init_diag=8,
827836
init_conv_tol=1e-3, init_max_iter=10,
828837
precond_conv_tol=1e-2, precond_max_iter=10,
829-
init_restart_iter=None, precond_restart_iter=None, restart_iter=None,
830-
in_ram=False, print_eigeneV_along=False):
838+
init_restart_subspace=None, precond_restart_subspace=None, restart_subspace=None,
839+
in_ram=False):
831840
'''
832841
Wrapper for Krylov solver to handle preconditioned eigenvalue, linear, or shifted linear problems.
833842
requires the non-diagonal approximation of A matrix, i.e., ris approximation.
@@ -892,7 +901,7 @@ def nested_krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue'
892901
problem_type=init_problem_type, hdiag=hdiag,
893902
matrix_vector_product=init_mvp,
894903
conv_tol=init_conv_tol, max_iter=init_max_iter,
895-
restart_iter=init_restart_iter,
904+
restart_subspace=init_restart_subspace,
896905
gram_schmidt=gram_schmidt, single=single, verbose=log.verbose-2
897906
)
898907
else:
@@ -909,7 +918,7 @@ def nested_krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue'
909918
problem_type=precond_problem_type, hdiag=hdiag,
910919
matrix_vector_product=precond_mvp,
911920
conv_tol=precond_conv_tol, max_iter=precond_max_iter,
912-
restart_iter=precond_restart_iter,
921+
restart_subspace=precond_restart_subspace,
913922
gram_schmidt=gram_schmidt, single=single, verbose=log.verbose-1
914923
)
915924
else:
@@ -928,7 +937,7 @@ def nested_krylov_solver(matrix_vector_product, hdiag, problem_type='eigenvalue'
928937
initguess_fn=initguess_fn, precond_fn=precond_fn,
929938
conv_tol=conv_tol, max_iter=max_iter,
930939
gram_schmidt=gram_schmidt, single=single, verbose=verbose,
931-
restart_iter=restart_iter, in_ram=in_ram, print_eigeneV_along=print_eigeneV_along,
940+
restart_subspace=restart_subspace, in_ram=in_ram
932941
)
933942
log.info(RIS_PRECOND_CITATION_INFO)
934943
return output

0 commit comments

Comments
 (0)