Skip to content

Commit 330098e

Browse files
author
Satinderpreet Singh
committed
Updated ML branch to do inference once per MPI rank
1 parent 06cf201 commit 330098e

1 file changed

Lines changed: 71 additions & 53 deletions

File tree

src_MFsurfchem/MFsurfchem_functions.cpp

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,14 @@ void sample_MFsurfchem(MultiFab& cu, MultiFab& prim, MultiFab& surfcov, MultiFab
173173
const GpuArray<Real, AMREX_SPACEDIM> dx = geom.CellSizeArray();
174174

175175
#ifdef AMREX_USE_ML
176-
bool model_loaded = false;
177-
torch::jit::script::Module model;
176+
static bool model_loaded = false;
177+
static torch::jit::script::Module model;
178178
auto dtype0 = torch::kFloat64;
179179

180180
// Default tensoropt to CPU
181-
auto tensoropt = torch::TensorOptions().dtype(dtype0);
181+
static auto tensoropt = torch::TensorOptions().dtype(dtype0);
182182
BL_PROFILE_VAR("load_ML_model", p_load);
183-
if (use_ml_mfsurfchem > 0) {
183+
if (use_ml_mfsurfchem > 0 && !model_loaded) {
184184
try {
185185
model = torch::jit::load(model_filename);
186186
model.eval();
@@ -215,37 +215,42 @@ void sample_MFsurfchem(MultiFab& cu, MultiFab& prim, MultiFab& surfcov, MultiFab
215215
#else
216216
BL_PROFILE_VAR_START(p_compute_ml);
217217

218+
if (!model_loaded) {
219+
Abort("ML model requested but not loaded");
220+
}
221+
// number of inputs and outputs of the pytorch model
222+
int Nc_in = 3;
223+
int Nc_out = 2;
224+
225+
// calculate total cells across all boxes to get size of the batch
226+
long total_cells = 0;
227+
std::vector<long> box_offsets;
218228
for (MFIter mfi(*surfcov_slice,false); mfi.isValid(); ++mfi)
219229
{
230+
box_offsets.push_back(total_cells);
220231
const Box& bx = mfi.tilebox();
221-
const Array4<Real> & cu_arr = cu.array(mfi);
222-
const Array4<Real> & prim_arr = prim.array(mfi);
223-
const Array4<Real> & surfcov_arr = surfcov_slice->array(mfi);
224-
const Array4<Real> & dNadsdes_arr = dNadsdes.array(mfi);
225-
const Array4<Real> & dNads_arr = dNads.array(mfi);
226-
const Array4<Real> & dNdes_arr = dNdes.array(mfi);
227-
228-
amrex::Real Ntot = surf_site_num_dens*dx[(ads_wall_dir+1)%3]*dx[(ads_wall_dir+2)%3]; // total number of reactive sites
229-
230-
if (!model_loaded) {
231-
Abort("ML model requested but not loaded");
232-
}
233-
// number of inputs and outputs of the pytorch model
234-
int Nc_in = 3;
235-
int Nc_out = 2;
236-
237-
//retrieve smallend and size of box
238-
const IntVect bx_lo = bx.smallEnd();
239232
const IntVect nbox = bx.size();
240233
int ncell = AMREX_SPACEDIM == 2 ?
241234
nbox[0] * nbox[1] : nbox[0] * nbox[1] * nbox[2];
242-
int nsample = ncell * n_ads_spec;
235+
total_cells += ncell;
236+
}
237+
238+
int total_samples = total_cells * n_ads_spec;
243239

244-
// creates a flattened buffer of total sample points on box times number of inputs on each point (total number of inputs)
245-
amrex::Gpu::ManagedVector<Real> aux(nsample * Nc_in);
240+
// creates a flattened buffer of total sample points
241+
amrex::Gpu::ManagedVector<Real> aux(total_samples * Nc_in);
242+
Real* AMREX_RESTRICT auxPtr = aux.dataPtr();
246243

247-
// gives pointer access to the buffer
248-
Real* AMREX_RESTRICT auxPtr = aux.dataPtr();
244+
// pack data from all boxes into the single buffer
245+
int box_idx = 0;
246+
for (MFIter mfi(*surfcov_slice,false); mfi.isValid(); ++mfi, ++box_idx)
247+
{
248+
const Box& bx = mfi.tilebox();
249+
const Array4<Real> & prim_arr = prim.array(mfi);
250+
const Array4<Real> & surfcov_arr = surfcov_slice->array(mfi);
251+
const IntVect bx_lo = bx.smallEnd();
252+
const IntVect nbox = bx.size();
253+
long offset = box_offsets[box_idx];
249254

250255
amrex::ParallelFor(bx, n_ads_spec, [=] AMREX_GPU_DEVICE (int i, int j, int k, int m) noexcept
251256
{
@@ -256,32 +261,47 @@ void sample_MFsurfchem(MultiFab& cu, MultiFab& prim, MultiFab& surfcov, MultiFab
256261
int kk = k - bx_lo[2];
257262
cell += kk*nbox[0]*nbox[1];
258263
#endif
259-
int index = cell * n_ads_spec + m;
264+
long index = (offset + cell) * n_ads_spec + m;
260265

261266
amrex::Real pres = 0.0;
262267
amrex::Real tempratio = prim_arr(i,j,k,4) / T_init[0];
263268
amrex::Real theta = 0.0;
264269

265-
pres = prim_arr(i,j,k,5);
266-
pres *= prim_arr(i,j,k,6 + nspecies + m);
267-
theta = surfcov_arr(i,j,k,m);
270+
pres = prim_arr(i,j,k,5);
271+
pres *= prim_arr(i,j,k,6 + nspecies + m);
272+
theta = surfcov_arr(i,j,k,m);
268273

269274
auxPtr[index*Nc_in + 0] = pres;
270275
auxPtr[index*Nc_in + 1] = tempratio;
271276
auxPtr[index*Nc_in + 2] = theta;
272277
});
278+
}
273279

274-
275-
at::Tensor inputs_torch = torch::from_blob(auxPtr, {nsample, Nc_in}, tensoropt);
276-
277-
at::Tensor outputs_torch = model.forward({inputs_torch}).toTensor();
278-
outputs_torch = outputs_torch.to(dtype0).contiguous();
280+
// run pytorch model once for all data
281+
at::Tensor inputs_torch = torch::from_blob(auxPtr, {total_samples, Nc_in}, tensoropt);
282+
at::Tensor outputs_torch = model.forward({inputs_torch}).toTensor();
283+
outputs_torch = outputs_torch.to(dtype0).contiguous();
279284

280285
#ifdef AMREX_USE_CUDA
281-
auto outputs_torch_acc = outputs_torch.packed_accessor64<Real,2>();
286+
auto outputs_torch_acc = outputs_torch.packed_accessor64<Real,2>();
282287
#else
283-
auto outputs_torch_acc = outputs_torch.accessor<Real,2>();
288+
auto outputs_torch_acc = outputs_torch.accessor<Real,2>();
284289
#endif
290+
291+
amrex::Real Ntot = surf_site_num_dens*dx[(ads_wall_dir+1)%3]*dx[(ads_wall_dir+2)%3];
292+
293+
// unpack data from pytorch results back to the amrex arrays
294+
box_idx = 0;
295+
for (MFIter mfi(*surfcov_slice,false); mfi.isValid(); ++mfi, ++box_idx)
296+
{
297+
const Box& bx = mfi.tilebox();
298+
const Array4<Real> & dNadsdes_arr = dNadsdes.array(mfi);
299+
const Array4<Real> & dNads_arr = dNads.array(mfi);
300+
const Array4<Real> & dNdes_arr = dNdes.array(mfi);
301+
const IntVect bx_lo = bx.smallEnd();
302+
const IntVect nbox = bx.size();
303+
long offset = box_offsets[box_idx];
304+
285305
amrex::ParallelForRNG(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k, RandomEngine const& engine) noexcept
286306
{
287307
int ii = i - bx_lo[0];
@@ -291,32 +311,30 @@ void sample_MFsurfchem(MultiFab& cu, MultiFab& prim, MultiFab& surfcov, MultiFab
291311
int kk = k - bx_lo[2];
292312
cell += kk*nbox[0]*nbox[1];
293313
#endif
314+
for (int m=0;m<n_ads_spec;m++) {
315+
long index = (offset + cell) * n_ads_spec + m;
294316

295-
for (int m=0;m<n_ads_spec;m++) {
296-
int index = cell * n_ads_spec + m;
297-
298-
amrex::Real pred_ads = static_cast<amrex::Real>(outputs_torch_acc[index][0]);
299-
amrex::Real pred_des = static_cast<amrex::Real>(outputs_torch_acc[index][1]);
317+
amrex::Real pred_ads = static_cast<amrex::Real>(outputs_torch_acc[index][0]);
318+
amrex::Real pred_des = static_cast<amrex::Real>(outputs_torch_acc[index][1]);
300319

301-
amrex::Real meanNads = pred_ads * Ntot * dt;
302-
amrex::Real meanNdes = pred_des * Ntot * dt;
320+
amrex::Real meanNads = pred_ads * Ntot * dt;
321+
amrex::Real meanNdes = pred_des * Ntot * dt;
303322

304-
amrex::Real Nads = (stoch_MFsurfchem == 0) ? meanNads : amrex::RandomPoisson(meanNads,engine);
305-
amrex::Real Ndes = (stoch_MFsurfchem == 0) ? meanNdes : amrex::RandomPoisson(meanNdes,engine);
323+
amrex::Real Nads = (stoch_MFsurfchem == 0) ? meanNads : amrex::RandomPoisson(meanNads,engine);
324+
amrex::Real Ndes = (stoch_MFsurfchem == 0) ? meanNdes : amrex::RandomPoisson(meanNdes,engine);
306325

307-
if (conversion_MFsurfchem > 0) {
308-
dNads_arr(i,j,k,m) = Nads;
309-
dNdes_arr(i,j,k,m) = Ndes;
310-
} else {
326+
if (conversion_MFsurfchem > 0) {
327+
dNads_arr(i,j,k,m) = Nads;
328+
dNdes_arr(i,j,k,m) = Ndes;
329+
} else {
311330
dNadsdes_arr(i,j,k,m) = Nads - Ndes;
312-
}
313331
}
332+
}
314333
});
315334
}
316335

317336
BL_PROFILE_VAR_STOP(p_compute_ml);
318337
#endif
319-
320338
} else { // use_ml_mfsurfchem <= 0
321339

322340
BL_PROFILE_VAR_START(p_compute_std);

0 commit comments

Comments
 (0)