From c31eff41d23bf68c4e20b732f06cca0ae104fd89 Mon Sep 17 00:00:00 2001 From: Craig Warren Date: Thu, 17 Oct 2019 16:08:59 +0100 Subject: [PATCH] Work to add detection and setting of GPUs. --- gprMax/config.py | 40 +++++++++++++++++++++++++++++++++------ gprMax/grid.py | 4 ++-- gprMax/model_build_run.py | 6 +++--- gprMax/utilities.py | 7 ++++--- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/gprMax/config.py b/gprMax/config.py index 4945227c..bb584975 100644 --- a/gprMax/config.py +++ b/gprMax/config.py @@ -29,6 +29,7 @@ from scipy.constants import c from scipy.constants import epsilon_0 as e0 from scipy.constants import mu_0 as m0 +from .utilities import detect_check_gpus from .utilities import get_host_info from .utilities import get_terminal_width @@ -53,15 +54,17 @@ class ModelConfig: """ self.i = model_num # Indexed from 0 + self.mode = '3D' self.grids = [] self.ompthreads = None # Number of OpenMP threads - # Store information for CUDA solver type + # Store information for CUDA solver # gpu: GPU object # snapsgpu2cpu: copy snapshot data from GPU to CPU during simulation # N.B. This will happen if the requested snapshots are too large to fit # on the memory of the GPU. If True this will slow performance significantly - self.cuda = {'gpu': None, 'snapsgpu2cpu': False} + if sim_config.general['cuda']: + self.cuda = {'gpu': sim_config.cuda['gpus'], 'snapsgpu2cpu': False} # Total memory usage for all grids in the model. Starts with 50MB overhead. self.mem_use = 50e6 @@ -144,7 +147,6 @@ class SimulationConfig: # outputfilepath: path to outputfile location # messages: whether to print all messages as output to stdout or not # progressbars: whether to show progress bars on stdoout or not - # mode: 2D TMx, 2D TMy, 2D TMz, or 3D # cpu, cuda, opencl: solver type # precision: data type for electromagnetic field output (single/double) # autotranslate: auto translate objects with main grid coordinates @@ -153,12 +155,12 @@ class SimulationConfig: # within the global subgrid space. self.general = {'messages': True, 'progressbars': True, - 'mode': '3D', 'cpu': True, 'cuda': False, 'opencl': False, 'precision': 'single', 'autotranslate': False} + log.debug('Should autotranslate be a ModelConfig parameter?') self.em_consts = {'c': c, # Speed of light in free space (m/s) 'e0': e0, # Permittivity of free space (F/m) @@ -168,8 +170,17 @@ class SimulationConfig: # Store information about host machine self.hostinfo = get_host_info() - # Information about any GPUs as a list of GPU objects - self.cuda_gpus = [] + # Information about any Nvidia GPUs + if self.args.gpu is not None: + self.general['cuda'] = True + self.general['cpu'] = False + self.general['opencl'] = False + # gpus: list of GPU objects + # gpus_str: list of strings describing GPU(s) + self.cuda = {'gpus': [], + 'gpus_str': []} + self.get_gpus() + self.set_gpus() # Subgrid parameter may not exist if user enters via CLI try: @@ -193,6 +204,19 @@ class SimulationConfig: def is_messages(self): return self.general['messages'] + def get_gpus(self): + """Get information and setup any Nvidia GPU(s).""" + # Flatten a list of lists + if any(isinstance(element, list) for element in self.args.gpu): + self.cuda['gpus'] = [val for sublist in self.args.gpu for val in sublist] + + self.cuda['gpus'], self.cuda['gpus_str'] = detect_check_gpus(self.cuda['gpus']) + + def set_gpus(self): + """Adjust list of GPU object(s) to specify single GPU.""" + self.cuda['gpus'] = self.cuda['gpus'][0] + self.cuda['gpus_str'] = self.cuda['gpus_str'][0] + def set_precision(self): """Data type (precision) for electromagnetic field output. @@ -268,3 +292,7 @@ class SimulationConfigMPI(SimulationConfig): # Set range for number of models to run self.model_start = self.args.restart if self.args.restart else 1 self.model_end = self.modelstart + self.args.n + + def set_gpus(self): + """Leave list of GPU object(s) as multi-object list.""" + pass diff --git a/gprMax/grid.py b/gprMax/grid.py index 2b36edec..5c529d5c 100644 --- a/gprMax/grid.py +++ b/gprMax/grid.py @@ -421,9 +421,9 @@ def dispersion_analysis(G): minwavelength = minvelocity / results['maxfreq'] # Maximum spatial step - if '3D' in config.sim_config.general['mode']: + if '3D' in config.model_configs[G.model_num].mode: delta = max(G.dx, G.dy, G.dz) - elif '2D' in config.sim_config.general['mode']: + elif '2D' in config.model_configs[G.model_num].mode: if G.nx == 1: delta = max(G.dy, G.dz) elif G.ny == 1: diff --git a/gprMax/model_build_run.py b/gprMax/model_build_run.py index 3760671b..8e950975 100644 --- a/gprMax/model_build_run.py +++ b/gprMax/model_build_run.py @@ -362,11 +362,11 @@ class GridBuilder: pbar.close() def tm_grid_update(self): - if '2D TMx' == config.sim_config.general['mode']: + if '2D TMx' == config.model_configs[self.grid.model_num].mode: self.grid.tmx() - elif '2D TMy' == config.sim_config.general['mode']: + elif '2D TMy' == config.model_configs[self.grid.model_num].mode: self.grid.tmy() - elif '2D TMz' == config.sim_config.general['mode']: + elif '2D TMz' == config.model_configs[self.grid.model_num].mode: self.grid.tmz() def update_voltage_source_materials(self): diff --git a/gprMax/utilities.py b/gprMax/utilities.py index 47a85b92..a5973d48 100644 --- a/gprMax/utilities.py +++ b/gprMax/utilities.py @@ -447,6 +447,7 @@ def detect_check_gpus(deviceIDs): Returns: gpus (list): Detected GPU(s) object(s). + gpus_str (list): Printable strings of information on GPU(s). """ try: @@ -475,15 +476,15 @@ def detect_check_gpus(deviceIDs): # Gather information about selected/detected GPUs gpus = [] - allgpustext = [] + gpus_str = [] for ID in deviceIDsavail: gpu = GPU(deviceID=ID) gpu.get_gpu_info(drv) if ID in deviceIDs: gpus.append(gpu) - allgpustext.append(f'{gpu.deviceID} - {gpu.name}, {human_size(gpu.totalmem, a_kilobyte_is_1024_bytes=True)}') + gpus_str.append(f'{gpu.deviceID} - {gpu.name}, {human_size(gpu.totalmem, a_kilobyte_is_1024_bytes=True)}') - return gpus, allgpustext + return gpus, gpus_str def timer():