Skip to content

Commit 2463549

Browse files
authored
Merge branch 'revert-7175-bartgol/eamxx/io-decomp-upgrade' (PR #7220)
Reverts #7175
2 parents 0697327 + 1de7f97 commit 2463549

9 files changed

+192
-190
lines changed

components/eamxx/src/share/io/eamxx_scorpio_interface.cpp

Lines changed: 85 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@
1313
namespace scream {
1414
namespace scorpio {
1515

16-
struct OffsetsVec {
17-
OffsetsVec (int n) : vec(n,-1) {}
18-
std::vector<PIO_Offset> vec;
19-
};
20-
2116
// This class is an implementation detail, and therefore it is hidden inside
2217
// a cpp file. All customers of IO capabilities must use the common interfaces
2318
// exposed in the header file of this source file.
@@ -348,11 +343,9 @@ void init_subsystem(const ekat::Comm& comm, const int atm_id)
348343
// Unused in standalone mode
349344
(void) atm_id;
350345
#endif
351-
static_assert (std::is_same<PIO_Offset,int>::value or
352-
std::is_same<PIO_Offset,long>::value or
353-
std::is_same<PIO_Offset,long long>::value,
354-
"Error! PIO was configured with PIO_OFFSET not in [int, long, long long]. EAMxx does not support that\n");
355346

347+
static_assert (sizeof(offset_t)==sizeof(PIO_Offset),
348+
"Error! PIO was configured with PIO_OFFSET not a 64-bit int.\n");
356349
}
357350

358351
bool is_subsystem_inited () {
@@ -369,19 +362,19 @@ void finalize_subsystem ()
369362
EKAT_REQUIRE_MSG (s.pio_sysid!=-1,
370363
"Error! PIO subsystem was already finalized.\n");
371364

372-
for (const auto& [filename,file] : s.files) {
373-
EKAT_REQUIRE_MSG (file.num_customers==0,
365+
for (auto& it : s.files) {
366+
EKAT_REQUIRE_MSG (it.second.num_customers==0,
374367
"Error! ScorpioSession::finalize called, but a file is still in use elsewhere.\n"
375-
" - filename: " + filename + "\n");
368+
" - filename: " + it.first + "\n");
376369
}
377370
s.files.clear();
378371

379-
for (const auto& [dimname,decomp] : s.decomps) {
380-
EKAT_REQUIRE_MSG (decomp.use_count()==1,
372+
for (auto& it : s.decomps) {
373+
EKAT_REQUIRE_MSG (it.second.use_count()==1,
381374
"Error! ScorpioSession::finalize called, but a decomp is still stored elsewhere.\n"
382-
" - decomp name: " + dimname + "\n");
375+
" - decomp name: " + it.first + "\n");
383376

384-
int err = PIOc_freedecomp(s.pio_sysid,decomp->ncid);
377+
int err = PIOc_freedecomp(s.pio_sysid,it.second->ncid);
385378
check_scorpio_noerr(err,"finalize_subsystem","freedecomp");
386379
}
387380
s.decomps.clear();
@@ -464,9 +457,9 @@ void register_file (const std::string& filename,
464457

465458
auto find_dim = [&](int dimid) -> std::shared_ptr<const PIODim> {
466459
std::shared_ptr<const PIODim> d;
467-
for (auto& [dimname,dim] : f.dims) {
468-
if (dim->ncid==dimid) {
469-
d = dim;
460+
for (auto it : f.dims) {
461+
if (it.second->ncid==dimid) {
462+
d = it.second;
470463
}
471464
}
472465
EKAT_REQUIRE_MSG (d!=nullptr,
@@ -685,7 +678,7 @@ int get_dimlen_local (const std::string& filename, const std::string& dimname)
685678
" - dimname : " + dimname + "\n");
686679

687680
const auto& dim = pf.file->dims.at(dimname);
688-
return dim->decomposed ? dim->offsets.size() : dim->length;
681+
return dim->offsets==nullptr ? dim->length : dim->offsets->size();
689682
}
690683

691684
bool has_time_dim (const std::string& filename)
@@ -737,9 +730,10 @@ void reset_time_dim_len (const std::string& filename, const int new_length)
737730
f.time_dim->length = new_length;
738731

739732
// Reset number of records counter for each time dep var
740-
for (auto& [varname,var] : f.vars) {
741-
if (var->time_dep) {
742-
var->num_records = new_length;
733+
for (auto it : f.vars) {
734+
auto& v = *it.second;
735+
if (v.time_dep) {
736+
v.num_records = new_length;
743737
}
744738
}
745739
}
@@ -752,31 +746,28 @@ void reset_time_dim_len (const std::string& filename, const int new_length)
752746
void set_var_decomp (PIOVar& var,
753747
const std::string& filename)
754748
{
749+
for (size_t i=1; i<var.dims.size(); ++i) {
750+
EKAT_REQUIRE_MSG (var.dims[i]->offsets==nullptr,
751+
"Error! We currently only allow decomposition on slowest-striding dimension.\n"
752+
" Generalizing is not complicated, but it was not a priority.\n"
753+
" - filename: " + filename + "\n"
754+
" - varname : " + var.name + "\n"
755+
" - var dims: " + ekat::join(var.dims,get_entity_name,",") + "\n"
756+
" - bad dim : " + var.dims[i]->name + "\n");
757+
}
758+
EKAT_REQUIRE_MSG (var.dims[0]->offsets!=nullptr,
759+
"Error! Calling set_var_decomp, but the var first dimension does not appear to be decomposed.\n"
760+
" - filename: " + filename + "\n"
761+
" - varname : " + var.name + "\n"
762+
" - var dims: " + ekat::join(var.dims,get_entity_name,",") + "\n");
755763
EKAT_REQUIRE_MSG (var.decomp==nullptr,
756764
"Error! You should have invalidated var.decomp before attempting to reset it.\n"
757765
" - filename : " + filename + "\n"
758766
" - varname : " + var.name + "\n"
759767
" - var decomp: " + var.decomp->name + "\n");
760768

761-
std::shared_ptr<const PIODim> decomp_dim;
762-
for (const auto& d : var.dims) {
763-
if (d->decomposed) {
764-
EKAT_REQUIRE_MSG (decomp_dim==nullptr,
765-
"Error! Variable has multiple decomposed dimensions.\n"
766-
" - file: " + filename + "\n"
767-
" - var : " + var.name + "\n"
768-
" - 1st decomp dim: " + decomp_dim->name + "\n"
769-
" - 2nd decomp dim: " + d->name + "\n");
770-
decomp_dim = d;
771-
}
772-
}
773-
EKAT_REQUIRE_MSG (decomp_dim!=nullptr,
774-
"Error! Calling set_var_decomp, but the var does not have any decomposde dimension.\n"
775-
" - filename: " + filename + "\n"
776-
" - varname : " + var.name + "\n"
777-
" - var dims: " + ekat::join(var.dims,get_entity_name,",") + "\n");
778-
779769
// Create decomp name: dtype-dim1<len1>_dim2<len2>_..._dimk<lenN>
770+
std::shared_ptr<const PIODim> decomp_dim;
780771
std::string decomp_tag = var.dtype + "-";
781772
for (auto d : var.dims) {
782773
decomp_tag += d->name + "<" + std::to_string(d->length) + ">_";
@@ -806,55 +797,34 @@ void set_var_decomp (PIOVar& var,
806797
// We haven't create this decomp yet. Go ahead and create one
807798
decomp = std::make_shared<PIODecomp>();
808799
decomp->name = decomp_tag;
809-
decomp->dim = decomp_dim;
800+
decomp->dim = var.dims[0];
810801

811802
int ndims = var.dims.size();
812803

813-
// Get local and global dim lengths
814-
std::vector<int> dimlen_glb(ndims),dimlen_lcl(ndims);
815-
int decomp_idx = -1;
816-
for (int idim=0; idim<ndims; ++idim) {
817-
dimlen_glb[idim] = dimlen_lcl[idim] = var.dims[idim]->length;
818-
if (var.dims[idim]->decomposed) {
819-
decomp_idx = idim;
820-
dimlen_lcl[idim] = var.dims[idim]->offsets.size();
821-
}
804+
// Get ALL dims global lengths, and compute prod of *non-decomposed* dims
805+
std::vector<int> gdimlen = {decomp->dim->length};
806+
int non_decomp_dim_prod = 1;
807+
for (int idim=1; idim<ndims; ++idim) {
808+
auto d = var.dims[idim];
809+
gdimlen.push_back(d->length);
810+
non_decomp_dim_prod *= d->length;
822811
}
823812

824-
// Compute global strides and local var size
825-
std::vector<int> strides(ndims,1);
826-
int ndofs_lcl = dimlen_lcl.back();
827-
for (int idim=ndims-2; idim>=0; --idim) {
828-
strides[idim] = strides[idim+1]*dimlen_glb[idim+1];
829-
ndofs_lcl *= dimlen_lcl[idim];
830-
}
831-
832-
std::vector<int> idx(ndims,0);
833-
834-
// Helper lambda, to update an Nd index by adding 1 the the right, and handling carries
835-
auto inc_idx = [&] () {
836-
for (int i=ndims-1; i>=0; --i) {
837-
++idx[i];
838-
if (idx[i]<dimlen_lcl[i])
839-
break;
840-
idx[i] = 0;
841-
}
842-
};
843-
844-
decomp->offsets = std::make_shared<OffsetsVec>(ndofs_lcl);
845-
for (int ldof=0; ldof<ndofs_lcl; ++ldof, inc_idx()) {
846-
int bkp = idx[decomp_idx];
847-
idx[decomp_idx] = decomp_dim->offsets[bkp];
848-
int gdof = std::inner_product(idx.begin(),idx.end(),strides.begin(),0);
849-
850-
decomp->offsets->vec[ldof] = gdof;
851-
idx[decomp_idx] = bkp;
813+
// Create offsets list
814+
const auto& dim_offsets = *decomp->dim->offsets;
815+
int dim_loc_len = dim_offsets.size();
816+
decomp->offsets.resize (non_decomp_dim_prod*dim_loc_len);
817+
for (int idof=0; idof<dim_loc_len; ++idof) {
818+
auto dof_offset = dim_offsets[idof];
819+
auto beg = decomp->offsets.begin()+ idof*non_decomp_dim_prod;
820+
auto end = beg + non_decomp_dim_prod;
821+
std::iota (beg,end,non_decomp_dim_prod*dof_offset);
852822
}
853823

854824
// Create PIO decomp
855-
int maplen = decomp->offsets->vec.size();
856-
PIO_Offset* compmap = decomp->offsets->vec.data();
857-
int err = PIOc_init_decomp(s.pio_sysid,nctype(var.dtype),ndims,dimlen_glb.data(),
825+
int maplen = decomp->offsets.size();
826+
PIO_Offset* compmap = reinterpret_cast<PIO_Offset*>(decomp->offsets.data());
827+
int err = PIOc_init_decomp(s.pio_sysid,nctype(var.dtype),ndims,gdimlen.data(),
858828
maplen,compmap, &decomp->ncid,s.pio_rearranger,
859829
nullptr,nullptr);
860830

@@ -867,7 +837,7 @@ void set_var_decomp (PIOVar& var,
867837

868838
void set_dim_decomp (const std::string& filename,
869839
const std::string& dimname,
870-
const std::vector<int>& my_offsets,
840+
const std::vector<offset_t>& my_offsets,
871841
const bool allow_reset)
872842
{
873843
auto& s = ScorpioSession::instance();
@@ -879,16 +849,17 @@ void set_dim_decomp (const std::string& filename,
879849
" - filename: " + filename + "\n"
880850
" - dimname : " + dimname + "\n");
881851

882-
if (dim.decomposed) {
852+
if (dim.offsets!=nullptr) {
883853
if (allow_reset) {
884854
// We likely won't need the previously created decomps that included this dimension.
885855
// So, as we remove decomps from vars that have this dim, keep track of their name,
886856
// so that we can free them later *if no other users of them remain*.
887857
std::set<std::string> decomps_to_remove;
888-
for (auto& [varname,var] : f.vars) {
889-
if (var->decomp!=nullptr and var->decomp->dim->name==dimname) {
890-
decomps_to_remove.insert(var->decomp->name);
891-
var->decomp = nullptr;
858+
for (auto it : f.vars) {
859+
auto v = it.second;
860+
if (v->decomp!=nullptr and v->decomp->dim->name==dimname) {
861+
decomps_to_remove.insert(v->decomp->name);
862+
v->decomp = nullptr;
892863
}
893864
}
894865
for (const auto& dn : decomps_to_remove) {
@@ -902,7 +873,7 @@ void set_dim_decomp (const std::string& filename,
902873
}
903874
} else {
904875
// Check that the offsets are (globally) the same
905-
int same = dim.offsets==my_offsets;
876+
int same = *dim.offsets==my_offsets;
906877
const auto& comm = ScorpioSession::instance().comm;
907878
comm.all_reduce(&same,1,MPI_MIN);
908879
EKAT_REQUIRE_MSG(same==1,
@@ -916,47 +887,33 @@ void set_dim_decomp (const std::string& filename,
916887
}
917888
}
918889

919-
#ifndef NDEBUG
920-
std::vector<int> all_offsets(dim.length);
921-
const auto& comm = ScorpioSession::instance().comm;
922-
// TODO: if you impl Comm::all_gather_v, use that.
923-
for (int pid=0, pos=0; pid<comm.size(); ++pid) {
924-
int n = my_offsets.size();
925-
comm.broadcast(&n,1,pid);
926-
auto buf = all_offsets.data()+pos;
927-
if (pid==comm.rank())
928-
std::copy(my_offsets.data(),my_offsets.data()+n,buf);
929-
comm.broadcast(buf,n,pid);
930-
pos += n;
890+
// Check that offsets are less than the global dimension length
891+
for (auto o : my_offsets) {
892+
EKAT_REQUIRE_MSG (o>=0 && o<dim.length,
893+
"Error! Offset for dimension decomposition is out of bounds.\n"
894+
" - filename: " + filename + "\n"
895+
" - dimname : " + dimname + "\n"
896+
" - dim glen: " + std::to_string(dim.length) + "\n"
897+
" - offset : " + std::to_string(o) + "\n");
931898
}
932899

933-
std::sort(all_offsets.begin(),all_offsets.end());
934-
std::vector<int> range(dim.length);
935-
std::iota(range.begin(),range.end(),0);
936-
EKAT_REQUIRE_MSG (range==all_offsets,
937-
"Error! The decomposition does not cover the global dim length.\n"
938-
" - filename: " + filename + "\n"
939-
" - dimname : " + dimname + "\n"
940-
" - all offsets (sorted): " + ekat::join(all_offsets,",") + "\n");
941-
#endif
942-
dim.offsets = my_offsets;
943-
dim.decomposed = true;
900+
dim.offsets = std::make_shared<std::vector<offset_t>>(my_offsets);
944901

945902
// If vars were already defined, we need to process them,
946903
// and create the proper PIODecomp objects.
947-
for (auto [varname,var] : f.vars) {
948-
if (ekat::contains(var->dim_names(),dimname)) {
949-
set_var_decomp (*var,filename);
904+
for (auto it : f.vars) {
905+
if (ekat::contains(it.second->dim_names(),dimname)) {
906+
set_var_decomp (*it.second,filename);
950907
}
951908
}
952909
}
953910

954911
void set_dim_decomp (const std::string& filename,
955912
const std::string& dimname,
956-
const int start, const int count,
913+
const offset_t start, const offset_t count,
957914
const bool allow_reset)
958915
{
959-
std::vector<int> offsets(count);
916+
std::vector<offset_t> offsets(count);
960917
std::iota(offsets.begin(),offsets.end(),start);
961918
set_dim_decomp(filename,dimname,offsets,allow_reset);
962919
}
@@ -973,7 +930,7 @@ void set_dim_decomp (const std::string& filename,
973930
++len;
974931
}
975932

976-
int offset = len;
933+
offset_t offset = len;
977934
comm.scan(&offset,1,MPI_SUM);
978935
offset -= len; // scan is inclusive, but we need exclusive
979936

@@ -1041,12 +998,8 @@ void define_var (const std::string& filename, const std::string& varname,
1041998
set_attribute(filename,varname,"units",units);
1042999
}
10431000

1044-
// Check if we need to setup at decomp for this var
1045-
for (const auto& d : var->dims) {
1046-
if (d->decomposed) {
1047-
set_var_decomp(*var,filename);
1048-
break;
1049-
}
1001+
if (var->dims.size()>0 and var->dims[0]->offsets!=nullptr) {
1002+
set_var_decomp (*var,filename);
10501003
}
10511004
} else {
10521005
const auto& var = f.vars.at(varname);
@@ -1174,11 +1127,12 @@ void mark_dim_as_time (const std::string& filename, const std::string& dimname)
11741127
// If a var has "time" in its dims (must be the 1st dim!),
11751128
// remove it. Recall that we only store non-time dims in
11761129
// the list of var dims.
1177-
for (auto& [varname,var] : f.vars) {
1178-
if (var->dims.size()>0 and var->dims[0]->name==dimname) {
1179-
var->dims.erase(var->dims.begin());
1180-
var->size = -1;
1181-
var->time_dep = true;
1130+
for (auto& it : f.vars) {
1131+
auto& v = it.second;
1132+
if (v->dims.size()>0 and v->dims[0]->name==dimname) {
1133+
v->dims.erase(v->dims.begin());
1134+
v->size = -1;
1135+
v->time_dep = true;
11821136
}
11831137
}
11841138
} else {
@@ -1258,7 +1212,7 @@ void read_var (const std::string &filename, const std::string &varname, T* buf,
12581212
std::string pioc_func;
12591213
if (var.decomp) {
12601214
// A decomposed variable, requires read_darray
1261-
err = PIOc_read_darray(f.ncid,var.ncid,var.decomp->ncid,var.decomp->offsets->vec.size(),buf);
1215+
err = PIOc_read_darray(f.ncid,var.ncid,var.decomp->ncid,var.decomp->offsets.size(),buf);
12621216
pioc_func = "read_darray";
12631217
} else {
12641218
// A non-decomposed variable, use PIOc_get_var(a)
@@ -1340,7 +1294,7 @@ void write_var (const std::string &filename, const std::string &varname, const T
13401294
std::string pioc_func;
13411295
if (var.decomp) {
13421296
// A decomposed variable, requires write_darray
1343-
err = PIOc_write_darray(f.ncid,var.ncid,var.decomp->ncid,var.decomp->offsets->vec.size(),buf,fillValue);
1297+
err = PIOc_write_darray(f.ncid,var.ncid,var.decomp->ncid,var.decomp->offsets.size(),buf,fillValue);
13441298
pioc_func = "write_darray";
13451299
} else {
13461300
// A non-decomposed variable, use PIOc_put_var(a)

components/eamxx/src/share/io/eamxx_scorpio_interface.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,12 @@ std::string get_time_name (const std::string& filename);
136136

137137
void set_dim_decomp (const std::string& filename,
138138
const std::string& dimname,
139-
const std::vector<int>& my_offsets,
139+
const std::vector<offset_t>& my_offsets,
140140
const bool allow_reset = false);
141141

142142
void set_dim_decomp (const std::string& filename,
143143
const std::string& dimname,
144-
const int start, const int count,
144+
const offset_t start, const offset_t count,
145145
const bool allow_reset = false);
146146

147147
void set_dim_decomp (const std::string& filename,

0 commit comments

Comments
 (0)