3 #ifndef DISTNTF_DISTNTFIO_HPP_ 4 #define DISTNTF_DISTNTFIO_HPP_ 33 static const int kPrimeOffset = 10;
35 static const int kW_seed_idx = 1210873;
36 static const int kalpha = 1;
37 static const int kbeta = 0;
45 void randomLowRank(
const UVEC i_global_dims,
const UVEC i_local_dims,
46 const UVEC i_start_rows,
const UWORD i_k) {
49 NCPFactors global_factors(i_global_dims, i_k,
false);
50 global_factors.
randu(kW_seed_idx);
52 NCPFactors local_factors(i_local_dims, i_k,
false);
53 UWORD start_row, end_row;
54 for (
int i = 0; i < local_factors.
modes(); i++) {
55 start_row = i_start_rows(i);
56 end_row = start_row + i_local_dims(i) - 1;
58 global_factors.
factor(i).rows(start_row, end_row);
117 : m_mpicomm(mpic), m_A(in) {}
163 UVEC *start_idxs_uvec = NULL) {
165 std::string filename_no_extension =
166 filename.substr(0, filename.find_last_of(
"."));
167 filename_no_extension.append(
".info");
172 ifs.open(filename_no_extension, std::ios_base::in);
178 int *local_dims =
new int[modes];
179 int *start_idxs =
new int[modes];
180 this->m_local_dims = arma::zeros<UVEC>(modes);
181 this->m_global_dims = arma::zeros<UVEC>(modes);
182 UVEC tmp_start_idxs_uvec = arma::zeros<UVEC>(modes);
184 for (
int i = 0; i < modes; i++) {
189 this->m_local_dims[i] = local_dims[i];
192 if (start_idxs_uvec != NULL) start_idxs_uvec[i] = start_idxs[i];
193 tmp_start_idxs_uvec[i] = start_idxs[i];
197 <<
"Local Tensor Dims::" << this->m_local_dims
198 <<
"::start_idxs::" << tmp_start_idxs_uvec);
199 Tensor rc(this->m_local_dims);
202 MPI_Type_create_subarray(modes,
global_dims, local_dims, start_idxs,
203 MPI_ORDER_FORTRAN, MPI_DOUBLE, &view);
204 MPI_Type_commit(&view);
209 int ret = MPI_File_open(MPI_COMM_WORLD, filename.c_str(), MPI_MODE_RDONLY,
211 if (ret != MPI_SUCCESS) {
212 DISTPRINTINFO(
"Error: Could not read file " << filename << std::endl);
216 MPI_File_set_view(fh, disp, MPI_DOUBLE, view,
"native", MPI_INFO_NULL);
218 int count = rc.
numel();
220 << (count * 8.0) / (1024 * 1024 * 1024));
221 assert(count * 8 <= std::numeric_limits<int>::max());
222 if (
ISROOT && 8 * count > std::numeric_limits<int>::max()) {
223 PRINTROOT(
"file read size ::" << 8.0 * count <<
" > 2GB" << std::endl);
226 ret = MPI_File_read_all(fh, &rc.
m_data[0], count, MPI_DOUBLE, &status);
228 MPI_Get_count(&status, MPI_DOUBLE, &nread);
229 if (ret != MPI_SUCCESS) {
230 DISTPRINTINFO(
"Error: Could not read file " << filename << std::endl);
235 MPI_Type_free(&view);
242 return this->m_global_dims;
254 const Tensor &local_tensor) {
256 std::string filename_no_extension =
257 filename.substr(0, filename.find_last_of(
"."));
258 int modes = local_tensor.
modes();
259 int *gsizes =
new int[modes];
260 int *lsizes =
new int[modes];
261 int *starts =
new int[modes];
263 for (
int i = 0; i < modes; i++) {
265 MPI_Allreduce(&lsizes[i], &gsizes[i], 1, MPI_INT, MPI_SUM,
266 this->m_mpicomm.
fiber(i));
272 filename_no_extension.append(
".info");
274 ofs.open(filename_no_extension, std::ios_base::out | std::ios::app);
276 ofs << modes << std::endl;
278 for (
int i = 0; i < modes; i++) {
279 ofs << gsizes[i] << std::endl;
283 MPI_Barrier(MPI_COMM_WORLD);
288 MPI_Type_create_subarray(modes, gsizes, lsizes, starts, MPI_ORDER_FORTRAN,
290 MPI_Type_commit(&view);
295 MPI_File_open(MPI_COMM_WORLD, filename.c_str(),
296 MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
297 if (
ISROOT && ret != MPI_SUCCESS) {
298 DISTPRINTINFO(
"Error: Could not open file " << filename << std::endl);
303 MPI_File_set_view(fh, disp, MPI_DOUBLE, view,
"native", MPI_INFO_NULL);
306 int count = local_tensor.
numel();
307 assert(count <= std::numeric_limits<int>::max());
309 ret = MPI_File_write_all(fh, &local_tensor.
m_data[0], count, MPI_DOUBLE,
311 if (ret != MPI_SUCCESS) {
312 DISTPRINTINFO(
"Error: Could not write file " << filename << std::endl);
317 MPI_Type_free(&view);
331 UVEC i_proc_grids,
UWORD k = 0,
double sparsity = 0) {
336 this->m_global_dims = i_global_dims;
337 std::string rand_prefix(
"rand_");
338 if (!file_name.compare(0, rand_prefix.size(), rand_prefix)) {
339 this->m_local_dims = arma::zeros<UVEC>(i_proc_grids.n_rows);
340 UVEC start_rows = arma::zeros<UVEC>(i_proc_grids.n_rows);
342 for (
unsigned int mode = 0; mode < this->m_local_dims.n_rows; mode++) {
343 int slice_num = this->m_mpicomm.
slice_num(mode);
344 this->m_local_dims[mode] =
345 itersplit(i_global_dims[mode], i_proc_grids[mode], slice_num);
347 startidx(i_global_dims[mode], i_proc_grids[mode], slice_num);
349 if (!file_name.compare(
"rand_uniform")) {
351 Tensor temp(this->m_local_dims, start_rows);
356 }
else if (!file_name.compare(
"rand_lowrank")) {
357 randomLowRank(i_global_dims, this->m_local_dims, start_rows, k);
365 std::stringstream sw;
366 for (
unsigned int i = 0; i < ntfsolver->
modes(); i++) {
367 sw << output_file_name <<
"_mode" << i <<
"_" <<
MPI_SIZE;
370 factort = arma::zeros<MAT>(ntfsolver->
rank(), this->m_global_dims[i]);
373 MPI_Barrier(MPI_COMM_WORLD);
374 ntfsolver->
factor(i, factort.memptr());
377 PRINTROOT(
"Writing factor " << i <<
" to " << sw.str());
378 MAT current_factor = factort.t();
379 current_factor.save(sw.str(), arma::raw_ascii);
381 MPI_Barrier(MPI_COMM_WORLD);
385 sw << output_file_name <<
"_lambda" 388 ntfsolver->
lambda().save(sw.str(), arma::raw_ascii);
398 #endif // DISTNTF_DISTNTFIO_HPP_ size_t rank() const
Low Rank.
void randu(const int i_seed)
initializes the local tensor with the given seed.
Data is stored such that the unfolding is column major.
void write(const std::string &output_file_name, DistAUNTF *ntfsolver)
int startidx(int n, int p, int r)
Returns the start idx of the current rank r for a global dimension n across p processes.
UVEC read_dist_tensor(const std::string filename, UVEC *start_idxs_uvec=NULL)
void rankk_tensor(Tensor &out)
Construct the rank k tensor out of the factor matrices Determine the KRP of the n-1 modes leaving out...
void normalize()
only during initialization. Reset's all lambda.
std::vector< double > m_data
int slice_num(int mode) const
#define DISTPRINTINFO(MSG)
int itersplit(int n, int p, int r)
The dimension a particular rank holds out of the global dimension n across p processes.
void swap(planc::Tensor &x, planc::Tensor &y)
UVEC proc_grids() const
Returns the process grid for which the communicators are setup.
DistNTFIO(const NTFMPICommunicator &mpic, Tensor &in)
void randu(const int i_seed=-1)
set the tensor with uniform random values starting with a seed.
void write_dist_tensor(const std::string filename, const Tensor &local_tensor)
Writes distributed tensor.
int modes() const
Return the number of modes. It is a scalar value.
const MPI_Comm & fiber(const int i) const
Returns the fiber communicator.
int fiber_rank(int i) const
Returns the fiber rank on a particular fiber grid.
void set_idx(const UVEC &i_start_idx)
int modes() const
returns number of modes
UWORD numel() const
Returns total number of elements.
int dimension(int i) const
Returns the dimension of the input mode.
void readInput(const std::string file_name, UVEC i_global_dims, UVEC i_proc_grids, UWORD k=0, double sparsity=0)
const NTFMPICommunicator & mpicomm() const
size_t modes() const
Returns the numbers of modes of the tensor.
ncp_factors contains the factors of the ncp every ith factor is of size n_i * k number of factors is ...
void factor(int mode, double *factor_matrix)
Returns the factor matrix by collected it across all the processors.
MAT & factor(const int i_n) const
factor matrix of a mode i_n
VEC lambda()
Returns the lambda of the NCP factors.