use logging package for output, and remove 'verbose' options

This commit is contained in:
Jan Petykiewicz 2017-05-20 21:30:14 -07:00
parent 4e3d4a8b2c
commit 4ffa5e4a66
3 changed files with 44 additions and 33 deletions

View File

@ -16,6 +16,7 @@ satisfy the constraints for the 'conjugate gradient' algorithm
from typing import Dict, Any from typing import Dict, Any
import time import time
import logging
import numpy import numpy
from numpy.linalg import norm from numpy.linalg import norm
@ -27,6 +28,11 @@ import fdfd_tools.solvers
from . import ops from . import ops
__author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
class CSRMatrix(object): class CSRMatrix(object):
""" """
Matrix stored in Compressed Sparse Row format, in GPU RAM. Matrix stored in Compressed Sparse Row format, in GPU RAM.
@ -49,7 +55,6 @@ def cg(A: 'scipy.sparse.csr_matrix',
err_threshold: float = 1e-6, err_threshold: float = 1e-6,
context: pyopencl.Context = None, context: pyopencl.Context = None,
queue: pyopencl.CommandQueue = None, queue: pyopencl.CommandQueue = None,
verbose: bool = False,
) -> numpy.ndarray: ) -> numpy.ndarray:
""" """
General conjugate-gradient solver for sparse matrices, where A @ x = b. General conjugate-gradient solver for sparse matrices, where A @ x = b.
@ -60,7 +65,6 @@ def cg(A: 'scipy.sparse.csr_matrix',
:param err_threshold: Error threshold for successful solve, relative to norm(b) :param err_threshold: Error threshold for successful solve, relative to norm(b)
:param context: PyOpenCL context. Will be created if not given. :param context: PyOpenCL context. Will be created if not given.
:param queue: PyOpenCL command queue. Will be created if not given. :param queue: PyOpenCL command queue. Will be created if not given.
:param verbose: Whether to print statistics to screen.
:return: Solution vector x; returned even if solve doesn't converge. :return: Solution vector x; returned even if solve doesn't converge.
""" """
@ -102,13 +106,11 @@ def cg(A: 'scipy.sparse.csr_matrix',
_, err2 = rhoerr_step(r, []) _, err2 = rhoerr_step(r, [])
b_norm = numpy.sqrt(err2) b_norm = numpy.sqrt(err2)
if verbose: logging.debug('b_norm check: ', b_norm)
print('b_norm check: ', b_norm)
success = False success = False
for k in range(max_iters): for k in range(max_iters):
if verbose: logging.debug('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha))
print('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha), end=' ')
rho_prev = rho rho_prev = rho
e = xr_step(x, p, r, v, alpha, []) e = xr_step(x, p, r, v, alpha, [])
@ -116,8 +118,7 @@ def cg(A: 'scipy.sparse.csr_matrix',
errs += [numpy.sqrt(err2) / b_norm] errs += [numpy.sqrt(err2) / b_norm]
if verbose: logging.debug('err {}'.format(errs[-1]))
print('err', errs[-1])
if errs[-1] < err_threshold: if errs[-1] < err_threshold:
success = True success = True
@ -128,7 +129,7 @@ def cg(A: 'scipy.sparse.csr_matrix',
alpha = rho / dot(p, v, e) alpha = rho / dot(p, v, e)
if verbose and k % 1000 == 0: if verbose and k % 1000 == 0:
print(k) logging.info('iteration {}'.format(k))
''' '''
Done solving Done solving
@ -137,17 +138,16 @@ def cg(A: 'scipy.sparse.csr_matrix',
x = x.get() x = x.get()
if verbose:
if success: if success:
print('Success', end='') logging.info('Solve success')
else: else:
print('Failure', end=', ') logging.warning('Solve failure')
print(', {} iterations in {} sec: {} iterations/sec \ logging.info('{} iterations in {} sec: {} iterations/sec \
'.format(k, time_elapsed, k / time_elapsed)) '.format(k, time_elapsed, k / time_elapsed))
print('final error', errs[-1]) logging.debug('final error {}'.format(errs[-1]))
print('overhead {} sec'.format(start_time2 - start_time)) logging.debug('overhead {} sec'.format(start_time2 - start_time))
print('Final residual:', norm(A @ x - b) / norm(b)) logging.info('Final residual: {}'.format(norm(A @ x - b) / norm(b)))
return x return x

View File

@ -8,6 +8,7 @@ a matrix).
from typing import List from typing import List
import time import time
import logging
import numpy import numpy
from numpy.linalg import norm from numpy.linalg import norm
@ -18,8 +19,11 @@ import fdfd_tools.operators
from . import ops from . import ops
__author__ = 'Jan Petykiewicz' __author__ = 'Jan Petykiewicz'
logger = logging.getLogger(__name__)
def cg_solver(omega: complex, def cg_solver(omega: complex,
dxes: List[List[numpy.ndarray]], dxes: List[List[numpy.ndarray]],
@ -32,7 +36,6 @@ def cg_solver(omega: complex,
max_iters: int = 40000, max_iters: int = 40000,
err_threshold: float = 1e-6, err_threshold: float = 1e-6,
context: pyopencl.Context = None, context: pyopencl.Context = None,
verbose: bool = False,
) -> numpy.ndarray: ) -> numpy.ndarray:
""" """
OpenCL FDFD solver using the iterative conjugate gradient (cg) method OpenCL FDFD solver using the iterative conjugate gradient (cg) method
@ -57,7 +60,6 @@ def cg_solver(omega: complex,
:param err_threshold: If (r @ r.conj()) / norm(1j * omega * J) < err_threshold, success. :param err_threshold: If (r @ r.conj()) / norm(1j * omega * J) < err_threshold, success.
Default 1e-6. Default 1e-6.
:param context: PyOpenCL context to run in. If not given, construct a new context. :param context: PyOpenCL context to run in. If not given, construct a new context.
:param verbose: If True, print progress to stdout. Default False.
:return: E-field which solves the system. Returned even if we did not converge. :return: E-field which solves the system. Returned even if we did not converge.
""" """
@ -171,12 +173,13 @@ def cg_solver(omega: complex,
_, err2 = rhoerr_step(r, []) _, err2 = rhoerr_step(r, [])
b_norm = numpy.sqrt(err2) b_norm = numpy.sqrt(err2)
print('b_norm check: ', b_norm) logging.debug('b_norm check: {}'.format(b_norm))
success = False success = False
for k in range(max_iters): for k in range(max_iters):
if verbose: do_print = (k % 100 == 0)
print('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha), end=' ') if do_print:
logger.debug('[{:06d}] rho {:.4} alpha {:4.4}'.format(k, rho, alpha))
rho_prev = rho rho_prev = rho
e = xr_step(x, p, r, v, alpha, []) e = xr_step(x, p, r, v, alpha, [])
@ -184,8 +187,8 @@ def cg_solver(omega: complex,
errs += [numpy.sqrt(err2) / b_norm] errs += [numpy.sqrt(err2) / b_norm]
if verbose: if do_print:
print('err', errs[-1]) logger.debug('err {}'.format(errs[-1]))
if errs[-1] < err_threshold: if errs[-1] < err_threshold:
success = True success = True
@ -196,7 +199,7 @@ def cg_solver(omega: complex,
alpha = rho / dot(p, v, e) alpha = rho / dot(p, v, e)
if k % 1000 == 0: if k % 1000 == 0:
print(k) logger.info('iteration {}'.format(k))
''' '''
Done solving Done solving
@ -210,18 +213,18 @@ def cg_solver(omega: complex,
x = (Pr * x).get() x = (Pr * x).get()
if success: if success:
print('Success', end='') logger.info('Solve success')
else: else:
print('Failure', end=', ') logger.warning('Solve failure')
print(', {} iterations in {} sec: {} iterations/sec \ logger.info('{} iterations in {} sec: {} iterations/sec \
'.format(k, time_elapsed, k / time_elapsed)) '.format(k, time_elapsed, k / time_elapsed))
print('final error', errs[-1]) logger.debug('final error {}'.format(errs[-1]))
print('overhead {} sec'.format(start_time2 - start_time)) logger.debug('overhead {} sec'.format(start_time2 - start_time))
A0 = fdfd_tools.operators.e_full(omega, dxes, epsilon, mu).tocsr() A0 = fdfd_tools.operators.e_full(omega, dxes, epsilon, mu).tocsr()
if adjoint: if adjoint:
# Remember we conjugated all the contents of A earlier # Remember we conjugated all the contents of A earlier
A0 = A0.T A0 = A0.T
print('Post-everything residual:', norm(A0 @ x - b) / norm(b)) logger.info('Post-everything residual: {}'.format(norm(A0 @ x - b) / norm(b)))
return x return x

View File

@ -8,6 +8,7 @@ See kernels/ for any of the .cl files loaded in this file.
""" """
from typing import List, Callable from typing import List, Callable
import logging
import numpy import numpy
import jinja2 import jinja2
@ -18,6 +19,8 @@ from pyopencl.elementwise import ElementwiseKernel
from pyopencl.reduction import ReductionKernel from pyopencl.reduction import ReductionKernel
logger = logging.getLogger(__name__)
# Create jinja2 env on module load # Create jinja2 env on module load
jinja_env = jinja2.Environment(loader=jinja2.PackageLoader(__name__, 'kernels')) jinja_env = jinja2.Environment(loader=jinja2.PackageLoader(__name__, 'kernels'))
@ -145,6 +148,11 @@ def create_a(context: pyopencl.Context,
e2 = H2E_kernel(E, H, oeps, Pl, pec, *idxes[1], wait_for=[e2]) e2 = H2E_kernel(E, H, oeps, Pl, pec, *idxes[1], wait_for=[e2])
return [e2] return [e2]
logger.debug('Preamble: \n{}'.format(preamble))
logger.debug('p2e: \n{}'.format(p2e_source))
logger.debug('e2h: \n{}'.format(e2h_source))
logger.debug('h2e: \n{}'.format(h2e_source))
return spmv return spmv