你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-08 07:24:19 +08:00
Work to get examples working on GPU.
这个提交包含在:
@@ -25,8 +25,8 @@ import gprMax.config as config
|
|||||||
from .cmds_geometry import UserObjectGeometry
|
from .cmds_geometry import UserObjectGeometry
|
||||||
from ..cython.geometry_primitives import build_voxels_from_array
|
from ..cython.geometry_primitives import build_voxels_from_array
|
||||||
from ..exceptions import CmdInputError
|
from ..exceptions import CmdInputError
|
||||||
from ..hash_cmds_file import check_cmd_names
|
# from ..hash_cmds_file import check_cmd_names
|
||||||
from ..hash_cmds_multiuse import process_multicmds
|
# from ..hash_cmds_multiuse import process_multicmds
|
||||||
from ..utilities import round_value
|
from ..utilities import round_value
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@@ -186,9 +186,7 @@ class SimulationConfig:
|
|||||||
'cpu': True,
|
'cpu': True,
|
||||||
'cuda': False,
|
'cuda': False,
|
||||||
'opencl': False,
|
'opencl': False,
|
||||||
'precision': 'single',
|
'precision': 'single'}
|
||||||
'autotranslate': self.args.autotranslate}
|
|
||||||
log.debug('Should autotranslate be a ModelConfig parameter?')
|
|
||||||
|
|
||||||
self.em_consts = {'c': c, # Speed of light in free space (m/s)
|
self.em_consts = {'c': c, # Speed of light in free space (m/s)
|
||||||
'e0': e0, # Permittivity of free space (F/m)
|
'e0': e0, # Permittivity of free space (F/m)
|
||||||
|
@@ -313,19 +313,17 @@ class CUDAGrid(FDTDGrid):
|
|||||||
self.bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) *
|
self.bpg = (int(np.ceil(((self.nx + 1) * (self.ny + 1) *
|
||||||
(self.nz + 1)) / self.tpb[0])), 1, 1)
|
(self.nz + 1)) / self.tpb[0])), 1, 1)
|
||||||
|
|
||||||
def initialise_geometry_arrays(self):
|
def initialise_geometry_arrays_gpu(self):
|
||||||
"""Initialise an array for cell edge IDs (ID) on GPU."""
|
"""Initialise an array for cell edge IDs (ID) on GPU."""
|
||||||
import pycuda.gpuarray as gpuarray
|
import pycuda.gpuarray as gpuarray
|
||||||
|
|
||||||
super().initialise_geometry_arrays()
|
|
||||||
self.ID_gpu = gpuarray.to_gpu(self.ID)
|
self.ID_gpu = gpuarray.to_gpu(self.ID)
|
||||||
|
|
||||||
def initialise_field_arrays(self):
|
def initialise_field_arrays_gpu(self):
|
||||||
"""Initialise geometry and field arrays on GPU."""
|
"""Initialise geometry and field arrays on GPU."""
|
||||||
|
|
||||||
import pycuda.gpuarray as gpuarray
|
import pycuda.gpuarray as gpuarray
|
||||||
|
|
||||||
super().initialise_field_arrays()
|
|
||||||
self.Ex_gpu = gpuarray.to_gpu(self.Ex)
|
self.Ex_gpu = gpuarray.to_gpu(self.Ex)
|
||||||
self.Ey_gpu = gpuarray.to_gpu(self.Ey)
|
self.Ey_gpu = gpuarray.to_gpu(self.Ey)
|
||||||
self.Ez_gpu = gpuarray.to_gpu(self.Ez)
|
self.Ez_gpu = gpuarray.to_gpu(self.Ez)
|
||||||
@@ -333,12 +331,19 @@ class CUDAGrid(FDTDGrid):
|
|||||||
self.Hy_gpu = gpuarray.to_gpu(self.Hy)
|
self.Hy_gpu = gpuarray.to_gpu(self.Hy)
|
||||||
self.Hz_gpu = gpuarray.to_gpu(self.Hz)
|
self.Hz_gpu = gpuarray.to_gpu(self.Hz)
|
||||||
|
|
||||||
def initialise_dispersive_arrays(self):
|
def initialise_grids_gpu(self):
|
||||||
|
"""Initialise all grids."""
|
||||||
|
for g in [self] + self.subgrids:
|
||||||
|
g.initialise_geometry_arrays_gpu()
|
||||||
|
g.initialise_field_arrays_gpu()
|
||||||
|
if config.model_configs[g.model_num].materials['maxpoles'] > 0:
|
||||||
|
g.initialise_dispersive_arrays_gpu()
|
||||||
|
|
||||||
|
def initialise_dispersive_arrays_gpu(self):
|
||||||
"""Initialise dispersive material coefficient arrays on GPU."""
|
"""Initialise dispersive material coefficient arrays on GPU."""
|
||||||
|
|
||||||
import pycuda.gpuarray as gpuarray
|
import pycuda.gpuarray as gpuarray
|
||||||
|
|
||||||
super().initialise_dispersive_arrays()
|
|
||||||
self.Tx_gpu = gpuarray.to_gpu(self.Tx)
|
self.Tx_gpu = gpuarray.to_gpu(self.Tx)
|
||||||
self.Ty_gpu = gpuarray.to_gpu(self.Ty)
|
self.Ty_gpu = gpuarray.to_gpu(self.Ty)
|
||||||
self.Tz_gpu = gpuarray.to_gpu(self.Tz)
|
self.Tz_gpu = gpuarray.to_gpu(self.Tz)
|
||||||
@@ -350,29 +355,26 @@ class CUDAGrid(FDTDGrid):
|
|||||||
super().reset_fields()
|
super().reset_fields()
|
||||||
|
|
||||||
# Clear arrays for field components
|
# Clear arrays for field components
|
||||||
self.initialise_field_arrays()
|
self.initialise_grids_gpu()
|
||||||
if config.model_configs[self.model_num].materials['maxpoles'] != 0:
|
|
||||||
self.initialise_dispersive_arrays()
|
|
||||||
|
|
||||||
# Clear arrays for fields in PML
|
# Clear arrays for fields in PML
|
||||||
for pml in self.pmls:
|
for pml in self.pmls:
|
||||||
pml.initialise_field_arrays()
|
pml.initialise_field_arrays_gpu()
|
||||||
|
|
||||||
def memory_check(self, snapsmemsize=0):
|
def memory_check(self, snapsmemsize=0):
|
||||||
"""Check if model can be run on specified GPU."""
|
"""Check if model can be run on specified GPU."""
|
||||||
|
|
||||||
super().memory_check()
|
memuse = super().mem_est_basic()
|
||||||
|
|
||||||
if config.cuda['gpus'] is not None:
|
if config.sim_config.general['cuda']
|
||||||
if self.memoryusage - snapsmemsize > config.cuda['gpus'].totalmem:
|
if memuse - snapsmemsize > config.model_configs[self.model_num].cuda['gpu'].totalmem:
|
||||||
raise GeneralError(f"Memory (RAM) required ~{human_size(self.memoryusage)} \
|
raise GeneralError(f"Memory (RAM) required ~{human_size(memuse)} exceeds {human_size(config.model_configs[self.model_num].cuda['gpu'].totalmem, a_kilobyte_is_1024_bytes=True)} detected on specified {config.model_configs[self.model_num].cuda['gpu'].deviceID} - {config.model_configs[self.model_num].cuda['gpu'].name} GPU!\n")
|
||||||
exceeds {human_size(config.cuda['gpus'].totalmem, a_kilobyte_is_1024_bytes=True)} \
|
|
||||||
detected on specified {config.cuda['gpus'].deviceID} - {config.cuda['gpus'].name} GPU!\n")
|
|
||||||
|
|
||||||
# If the required memory for the model without the snapshots will
|
# If the required memory for the model without the snapshots will
|
||||||
# fit on the GPU then transfer and store snaphots on host
|
# fit on the GPU then transfer and store snaphots on host
|
||||||
if snapsmemsize != 0 and self.memoryusage - snapsmemsize < config.cuda['gpus'].totalmem:
|
if (snapsmemsize != 0 and memuse - snapsmemsize <
|
||||||
config.cuda['snapsgpu2cpu'] = True
|
config.model_configs[self.model_num].cuda['gpu'].totalmem):
|
||||||
|
config.model_configs[self.model_num].cuda['snapsgpu2cpu'] = True
|
||||||
|
|
||||||
|
|
||||||
def dispersion_analysis(G):
|
def dispersion_analysis(G):
|
||||||
|
@@ -24,7 +24,7 @@ import sys
|
|||||||
|
|
||||||
import gprMax.config as config
|
import gprMax.config as config
|
||||||
from .exceptions import CmdInputError
|
from .exceptions import CmdInputError
|
||||||
# from .hash_cmds_geometry import process_geometrycmds
|
from .hash_cmds_geometry import process_geometrycmds
|
||||||
from .hash_cmds_multiuse import process_multicmds
|
from .hash_cmds_multiuse import process_multicmds
|
||||||
from .hash_cmds_singleuse import process_singlecmds
|
from .hash_cmds_singleuse import process_singlecmds
|
||||||
|
|
||||||
|
@@ -339,13 +339,11 @@ class CUDAPML(PML):
|
|||||||
solving on GPU using CUDA.
|
solving on GPU using CUDA.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def initialise_field_arrays(self):
|
def initialise_field_arrays_gpu(self):
|
||||||
"""Initialise PML field and coefficient arrays on GPU."""
|
"""Initialise PML field and coefficient arrays on GPU."""
|
||||||
|
|
||||||
import pycuda.gpuarray as gpuarray
|
import pycuda.gpuarray as gpuarray
|
||||||
|
|
||||||
super().initialise_field_arrays()
|
|
||||||
|
|
||||||
self.ERA_gpu = gpuarray.to_gpu(self.ERA)
|
self.ERA_gpu = gpuarray.to_gpu(self.ERA)
|
||||||
self.ERB_gpu = gpuarray.to_gpu(self.ERB)
|
self.ERB_gpu = gpuarray.to_gpu(self.ERB)
|
||||||
self.ERE_gpu = gpuarray.to_gpu(self.ERE)
|
self.ERE_gpu = gpuarray.to_gpu(self.ERE)
|
||||||
|
@@ -273,7 +273,7 @@ class CUDAUpdates:
|
|||||||
get kernel functions.
|
get kernel functions.
|
||||||
"""
|
"""
|
||||||
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0:
|
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0:
|
||||||
kernels_fields = self.source_module(kernels_template_fields.substitute(
|
kernels_fields = self.source_module(kernel_template_fields.substitute(
|
||||||
REAL=config.sim_config.dtypes['C_float_or_double'],
|
REAL=config.sim_config.dtypes['C_float_or_double'],
|
||||||
COMPLEX=config.sim_config.dtypes['C_complex'],
|
COMPLEX=config.sim_config.dtypes['C_complex'],
|
||||||
N_updatecoeffsE=self.grid.updatecoeffsE.size,
|
N_updatecoeffsE=self.grid.updatecoeffsE.size,
|
||||||
@@ -318,11 +318,10 @@ class CUDAUpdates:
|
|||||||
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0: # If there are any dispersive materials (updates are split into two parts as they require present and updated electric field values).
|
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0: # If there are any dispersive materials (updates are split into two parts as they require present and updated electric field values).
|
||||||
self.dispersive_update_a = kernels_fields.get_function("update_electric_dispersive_A")
|
self.dispersive_update_a = kernels_fields.get_function("update_electric_dispersive_A")
|
||||||
self.dispersive_update_b = kernels_fields.get_function("update_electric_dispersive_B")
|
self.dispersive_update_b = kernels_fields.get_function("update_electric_dispersive_B")
|
||||||
self.grid.initialise_dispersive_arrays()
|
|
||||||
|
|
||||||
# Electric and magnetic field updates - set blocks per grid and initialise field arrays on GPU
|
# Electric and magnetic field updates - set blocks per grid and initialise field arrays on GPU
|
||||||
self.grid.set_blocks_per_grid()
|
self.grid.set_blocks_per_grid()
|
||||||
self.grid.initialise_arrays()
|
self.grid.initialise_grids_gpu()
|
||||||
|
|
||||||
def set_pml_kernels(self):
|
def set_pml_kernels(self):
|
||||||
"""PMLS - prepare kernels and get kernel functions."""
|
"""PMLS - prepare kernels and get kernel functions."""
|
||||||
@@ -651,7 +650,7 @@ class CUDAUpdates:
|
|||||||
self.iterstart.record()
|
self.iterstart.record()
|
||||||
self.iterstart.synchronize()
|
self.iterstart.synchronize()
|
||||||
|
|
||||||
def calculate_memsolve(iteration):
|
def calculate_memsolve(self, iteration):
|
||||||
"""Calculate memory used on last iteration.
|
"""Calculate memory used on last iteration.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
14
setup.py
14
setup.py
@@ -29,7 +29,7 @@ except ImportError:
|
|||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import pathlib
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
@@ -156,9 +156,9 @@ if 'cleanall' in sys.argv:
|
|||||||
if os.path.isfile(filebase + '.c'):
|
if os.path.isfile(filebase + '.c'):
|
||||||
try:
|
try:
|
||||||
os.remove(filebase + '.c')
|
os.remove(filebase + '.c')
|
||||||
print(f'Removed: {filebase} + ".c"')
|
print(f'Removed: {filebase + ".c"}')
|
||||||
except OSError:
|
except OSError:
|
||||||
print(f'Could not remove: {filebase} + ".c"')
|
print(f'Could not remove: {filebase + ".c"}')
|
||||||
# Remove compiled Cython modules
|
# Remove compiled Cython modules
|
||||||
libfile = glob.glob(os.path.join(os.getcwd(), os.path.splitext(file)[0]) + '*.pyd') + glob.glob(os.path.join(os.getcwd(), os.path.splitext(file)[0]) + '*.so')
|
libfile = glob.glob(os.path.join(os.getcwd(), os.path.splitext(file)[0]) + '*.pyd') + glob.glob(os.path.join(os.getcwd(), os.path.splitext(file)[0]) + '*.so')
|
||||||
if libfile:
|
if libfile:
|
||||||
@@ -169,10 +169,10 @@ if 'cleanall' in sys.argv:
|
|||||||
except OSError:
|
except OSError:
|
||||||
print(f'Could not remove: {os.path.abspath(libfile)}')
|
print(f'Could not remove: {os.path.abspath(libfile)}')
|
||||||
# Remove build, dist, egg and __pycache__ directories
|
# Remove build, dist, egg and __pycache__ directories
|
||||||
shutil.rmtree(os.path.join(os.getcwd(), 'build'), ignore_errors=True)
|
shutil.rmtree(Path.cwd().joinpath('build'), ignore_errors=True)
|
||||||
shutil.rmtree(os.path.join(os.getcwd(), 'dist'), ignore_errors=True)
|
shutil.rmtree(Path.cwd().joinpath('dist'), ignore_errors=True)
|
||||||
shutil.rmtree(os.path.join(os.getcwd(), 'gprMax.egg-info'), ignore_errors=True)
|
shutil.rmtree(Path.cwd().joinpath('gprMax.egg-info'), ignore_errors=True)
|
||||||
for p in pathlib.Path(os.getcwd()).rglob('__pycache__'):
|
for p in Path.cwd().rglob('__pycache__'):
|
||||||
shutil.rmtree(p, ignore_errors=True)
|
shutil.rmtree(p, ignore_errors=True)
|
||||||
print(f'Removed: {p}')
|
print(f'Removed: {p}')
|
||||||
# Now do a normal clean
|
# Now do a normal clean
|
||||||
|
在新工单中引用
屏蔽一个用户