Zoltan2
Loading...
Searching...
No Matches
readMatrixFromBinaryFile.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef __READMATRIXFROMBINARYFILE_HPP
11#define __READMATRIXFROMBINARYFILE_HPP
12
14// These utilities read a sparse matrix from a binary file that was
15// created with the corresponding "largestComponent2Binary.cpp" code.
16// Specific structure may be assumed.
17// Note: This is research code. We do not guarantee it works in all cases.
19#include <climits>
20#include "Tpetra_Details_makeColMap.hpp"
21
22template <typename global_ordinal_type, typename local_ordinal_type, typename scalar_type, typename map_type>
23void
24distribute (Teuchos::ArrayRCP<size_t>& myNumEntriesPerRow,
25 Teuchos::ArrayRCP<size_t>& myRowPtr,
26 Teuchos::ArrayRCP<global_ordinal_type>& myColInd,
27 Teuchos::ArrayRCP<scalar_type>& myValues,
28 const Teuchos::RCP<const map_type>& pRowMap,
29 global_ordinal_type *rowPtr,
30 global_ordinal_type *colInd,
31 const bool debug=false)
32{
33
34 int maxNumEnt = INT_MAX/sizeof(global_ordinal_type);
35
36 Teuchos::RCP<const Teuchos::Comm<int>> pComm = pRowMap->getComm ();
37 const int numProcs = pComm->getSize ();
38 const int myRank = pComm->getRank ();
39 const int rootRank = 0;
40
41 Teuchos::ArrayView<const global_ordinal_type> myRows = pRowMap->getLocalElementList();
42 const size_t myNumRows = myRows.size();
43
44 myNumEntriesPerRow = Teuchos::ArrayRCP<size_t> (myNumRows);
45
46 if (myRank != rootRank) {
47
48 Teuchos::send (*pComm, myNumRows, rootRank);
49
50 if (myNumRows != 0) {
51
52 Teuchos::send (*pComm, static_cast<int> (myNumRows), myRows.getRawPtr(), rootRank);
53 Teuchos::receive (*pComm, rootRank, static_cast<int> (myNumRows), myNumEntriesPerRow.getRawPtr());
54
55 const global_ordinal_type myNumEntries =
56 std::accumulate (myNumEntriesPerRow.begin(),
57 myNumEntriesPerRow.end(), 0);
58
59 myColInd = Teuchos::ArrayRCP<global_ordinal_type> (myNumEntries);
60 myValues = Teuchos::ArrayRCP<scalar_type> (myNumEntries, 1.0);
61 if (myNumEntries > 0) {
62
63 if(myNumEntries < maxNumEnt)
64 Teuchos::receive (*pComm, rootRank, static_cast<int> (myNumEntries), &myColInd[0]);
65 else {
66 int nchunks = myNumEntries/maxNumEnt;
67 if(myNumEntries % maxNumEnt != 0)
68 nchunks ++;
69 for(int i = 0; i < nchunks-1; i++) {
70 Teuchos::receive (*pComm, rootRank, maxNumEnt, &myColInd[maxNumEnt*i]);
71 std::cout << "Chunk " << i << " received by myRank "<< myRank << ", size: " << maxNumEnt << "\n";
72 }
73 int lastsize = (int)(myNumEntries - (nchunks-1)*maxNumEnt);
74 Teuchos::receive (*pComm, rootRank, lastsize, &myColInd[maxNumEnt*(nchunks-1)]);
75 std::cout << "Chunk " << nchunks-1 << " received by myRank " << myRank << ", size: " << lastsize << "\n";
76 }
77
78 }
79
80 } // If I own at least one row
81
82 } // If I am not the root processor
83 else { // I _am_ the root processor
84 if (debug) {
85 std::cout << "-- Proc 0: Copying my data from global arrays" << std::endl;
86 }
87
88 for (size_t k = 0; k < myNumRows; ++k) {
89 const global_ordinal_type myCurRow = myRows[k];
90 const global_ordinal_type numEntriesInThisRow = rowPtr[myCurRow+1] - rowPtr[myCurRow];
91 myNumEntriesPerRow[k] = numEntriesInThisRow;
92
93 }
94
95 size_t myNumEntries = std::accumulate (myNumEntriesPerRow.begin(),
96 myNumEntriesPerRow.end(), 0);
97 if (debug) {
98 std::cout << "-- Proc 0: I own " << myNumRows << " rows and "
99 << myNumEntries << " entries" << std::endl;
100 }
101 myColInd = Teuchos::ArrayRCP<global_ordinal_type> (myNumEntries);
102 myValues = Teuchos::ArrayRCP<scalar_type> (myNumEntries, 1.0);
103
104 global_ordinal_type myCurPos = 0;
105 for (size_t k = 0; k < myNumRows; ++k) {
106 const global_ordinal_type curNumEntries = myNumEntriesPerRow[k];
107 const global_ordinal_type myRow = myRows[k];
108 global_ordinal_type curPos = rowPtr[myRow];
109
110 if (curNumEntries > 0) {
111 for(global_ordinal_type ii = 0; ii < curNumEntries; ++ii) {
112 myColInd[myCurPos++] = colInd[curPos++];
113 }
114 }
115 }
116
117 for (int p = 1; p < numProcs; ++p) {
118 if (debug) {
119 std::cout << "-- Proc 0: Processing proc " << p << std::endl;
120 }
121
122 size_t theirNumRows = 0;
123 Teuchos::receive (*pComm, p, &theirNumRows);
124 if (debug) {
125 std::cout << "-- Proc 0: Proc " << p << " owns "
126 << theirNumRows << " rows" << std::endl;
127 }
128
129 if (theirNumRows != 0) {
130 Teuchos::ArrayRCP<global_ordinal_type> theirRows(theirNumRows);
131 Teuchos::receive (*pComm, p, Teuchos::as<int> (theirNumRows), theirRows.getRawPtr ());
132
133 Teuchos::ArrayRCP<size_t> theirNumEntriesPerRow = Teuchos::ArrayRCP<size_t> (theirNumRows);
134 for (size_t k = 0; k < theirNumRows; ++k) {
135 theirNumEntriesPerRow[k] = rowPtr[theirRows[k]+1] - rowPtr[theirRows[k]];
136 }
137
138 Teuchos::send (*pComm, static_cast<int> (theirNumRows), theirNumEntriesPerRow.getRawPtr(), p);
139
140 const global_ordinal_type theirNumEntries =
141 std::accumulate (theirNumEntriesPerRow.begin(),
142 theirNumEntriesPerRow.end(), 0);
143
144 if (debug) {
145 std::cout << "-- Proc 0: Proc " << p << " owns "
146 << theirNumEntries << " entries" << std::endl;
147 }
148
149 if (theirNumEntries == 0) {
150 continue;
151 }
152
153 Teuchos::ArrayRCP<global_ordinal_type> theirColInd (theirNumEntries);
154
155 global_ordinal_type theirCurPos = 0;
156 for (size_t k = 0; k < theirNumRows; k++) {
157 const global_ordinal_type curNumEntries = theirNumEntriesPerRow[k];
158 const global_ordinal_type theirRow = theirRows[k];
159 global_ordinal_type curPos = rowPtr[theirRow];
160
161 if (curNumEntries > 0) {
162
163 for(global_ordinal_type ii = 0; ii < curNumEntries; ++ii) {
164 theirColInd[theirCurPos++] = colInd[curPos++];
165 }
166
167 }
168 }
169
170 if(theirNumEntries < maxNumEnt)
171 Teuchos::send (*pComm, static_cast<int> (theirNumEntries), &theirColInd[0], p);
172 else {
173 int nchunks = theirNumEntries/maxNumEnt;
174 if(theirNumEntries % maxNumEnt != 0)
175 nchunks ++;
176 for(int i = 0; i < nchunks-1; i++) {
177 Teuchos::send (*pComm, maxNumEnt, &theirColInd[maxNumEnt*i], p);
178 std::cout << "Chunk " << i << " sent to Rank "<< p << ", size: " << maxNumEnt << "\n";
179 }
180 int lastsize = (int)(theirNumEntries - (nchunks-1)*maxNumEnt);
181 Teuchos::send (*pComm, lastsize, &theirColInd[maxNumEnt*(nchunks-1)], p);
182 std::cout << "Chunk " << nchunks-1 << " sent to Rank "<< p << ", size: " << lastsize << "\n";
183 }
184
185 if (debug) {
186 std::cout << "-- Proc 0: Finished with proc " << p << std::endl;
187 }
188
189 } // If proc p owns at least one row
190 } // For each proc p not the root proc 0
191 } // If I'm (not) the root proc 0
192
193 if (debug && myRank == 0) {
194 std::cout << "-- Proc 0: About to fill in myRowPtr" << std::endl;
195 }
196
197 myRowPtr = Teuchos::ArrayRCP<size_t> (myNumRows+1);
198 myRowPtr[0] = 0;
199 for (size_t k = 1; k < myNumRows+1; ++k) {
200 myRowPtr[k] = myRowPtr[k-1] + myNumEntriesPerRow[k-1];
201 }
202 if (debug && myRank == 0) {
203 std::cout << "-- Proc 0: Done with distribute" << std::endl;
204 }
205}
206
207template <typename crs_matrix_type>
208Teuchos::RCP<crs_matrix_type>
209readBinaryFile(std::string filename, const Teuchos::RCP<const Teuchos::Comm<int>> pComm, bool callFillComplete=true, bool debug=false)
210{
211 typedef typename crs_matrix_type::global_ordinal_type global_ordinal_type;
212 typedef typename crs_matrix_type::local_ordinal_type local_ordinal_type;
213 typedef typename crs_matrix_type::scalar_type scalar_type;
214 typedef typename crs_matrix_type::node_type node_type;
215
216 typedef typename Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> map_type;
217
218 const int myRank = pComm->getRank();
219 const int rootRank = 0;
220
221 if (debug && myRank == rootRank) {
222 std::cout << "Binary CRS reader: readSparse:" << std::endl
223 << "-- Reading started" << std::endl;
224 }
225
226 Teuchos::RCP<std::ifstream> in;
227 global_ordinal_type globalNumRows;
228 global_ordinal_type globalNumNonzeros;
229
230 if (myRank == rootRank) {
231
232 // Open the file
233 in = Teuchos::RCP<std::ifstream>(new std::ifstream(filename, std::ios::in | std::ios::binary));
234
235 // Read number of vertices and number of edges
236 in->read((char *)&globalNumRows, sizeof(global_ordinal_type));
237 in->read((char *)&globalNumNonzeros, sizeof(global_ordinal_type));
238
239 TEUCHOS_TEST_FOR_EXCEPTION(globalNumRows <= 0 || globalNumNonzeros <= 0, std::invalid_argument,
240 "Global number of rows or nonzeros have nonpositive value." << globalNumRows << " " << globalNumNonzeros << " " << sizeof(global_ordinal_type) );
241 }
242
243 broadcast (*pComm, rootRank, 1, &globalNumRows);
244 broadcast (*pComm, rootRank, 1, &globalNumNonzeros);
245
246 global_ordinal_type *rowPtr = 0;
247 global_ordinal_type *colInd = 0;
248
249 if (myRank == rootRank) {
250
251 rowPtr = new global_ordinal_type[globalNumRows+1];
252 colInd = new global_ordinal_type[globalNumNonzeros];
253
254 in->read((char*)rowPtr, sizeof(global_ordinal_type)*(globalNumRows+1));
255 in->read((char*)colInd, sizeof(global_ordinal_type)*(globalNumNonzeros));
256 }
257
258 Teuchos::RCP<const map_type> pRowMap = Teuchos::rcp (new map_type (static_cast<Tpetra::global_size_t> (globalNumRows),
259 static_cast<global_ordinal_type> (0),
260 pComm, Tpetra::GloballyDistributed));
261
262 Teuchos::RCP<const map_type> pRangeMap = Teuchos::rcp (new map_type (static_cast<Tpetra::global_size_t> (globalNumRows),
263 static_cast<global_ordinal_type> (0),
264 pComm, Tpetra::GloballyDistributed));
265
266 Teuchos::RCP<const map_type> pDomainMap = pRangeMap;
267
268 Teuchos::ArrayView<const global_ordinal_type> myRows = pRowMap->getLocalElementList ();
269 const size_t myNumRows = myRows.size ();
270
271 Teuchos::ArrayRCP<size_t> myNumEntriesPerRow(myNumRows);
272 Teuchos::ArrayRCP<size_t> myRowPtr;
273 Teuchos::ArrayRCP<global_ordinal_type> myColInd;
274 Teuchos::ArrayRCP<scalar_type> myValues;
275
276 distribute<global_ordinal_type, local_ordinal_type, scalar_type, map_type>(myNumEntriesPerRow, myRowPtr, myColInd, myValues, pRowMap, rowPtr, colInd, debug);
277 pComm->barrier();
278
279 if (debug && myRank == rootRank) {
280 std::cout << "-- Inserting matrix entries on each processor";
281 if (callFillComplete) {
282 std::cout << " and calling fillComplete()";
283 }
284 std::cout << std::endl;
285 }
286
287 Teuchos::RCP<crs_matrix_type> pMatrix = Teuchos::rcp (new crs_matrix_type (pRowMap, myNumEntriesPerRow()));
288
289 const global_ordinal_type indexBase = pRowMap->getIndexBase ();
290 for (size_t i = 0; i < myNumRows; ++i) {
291 const size_t myCurPos = myRowPtr[i];
292 const local_ordinal_type curNumEntries = myNumEntriesPerRow[i];
293 Teuchos::ArrayView<global_ordinal_type> curColInd = myColInd.view (myCurPos, curNumEntries);
294 Teuchos::ArrayView<scalar_type> curValues = myValues.view (myCurPos, curNumEntries);
295
296 for (size_t k = 0; k < curNumEntries; ++k) {
297 curColInd[k] += indexBase;
298 }
299
300 if (curNumEntries > 0) {
301 pMatrix->insertGlobalValues (myRows[i], curColInd, curValues);
302 }
303 }
304 pComm->barrier();
305 if (debug && myRank == rootRank) {
306 std::cout << "-- Done with inserting." << std::endl;
307 }
308
309 myNumEntriesPerRow = Teuchos::null;
310 myRowPtr = Teuchos::null;
311 myColInd = Teuchos::null;
312 myValues = Teuchos::null;
313
314 if (callFillComplete) {
315 pMatrix->fillComplete (pDomainMap, pRangeMap);
316 }
317 pComm->barrier();
318 if (debug && myRank == rootRank) {
319 std::cout << "-- Done with fill complete." << std::endl;
320 }
321
322
323 if(myRank == rootRank) {
324 delete [] rowPtr;
325 delete [] colInd;
326 }
327
328 return pMatrix;
329}
330
331template <typename crs_matrix_type>
332Teuchos::RCP<crs_matrix_type>
333readBinaryFileFast(std::string filename, const Teuchos::RCP<const Teuchos::Comm<int>> pComm, bool callFillComplete=true, bool debug=false)
334{
335 typedef typename crs_matrix_type::global_ordinal_type global_ordinal_type;
336 typedef typename crs_matrix_type::local_ordinal_type local_ordinal_type;
337 typedef typename crs_matrix_type::scalar_type scalar_type;
338 typedef typename crs_matrix_type::node_type node_type;
339 typedef typename crs_matrix_type::crs_graph_type crs_graph_type;
340
341 typedef typename Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> map_type;
342
343 const int myRank = pComm->getRank();
344 const int rootRank = 0;
345
346 if (debug && myRank == rootRank) {
347 std::cout << "Binary CRS reader: readSparse:" << std::endl
348 << "-- Reading started" << std::endl;
349 }
350
351 Teuchos::RCP<std::ifstream> in;
352 global_ordinal_type globalNumRows;
353 global_ordinal_type globalNumNonzeros;
354
355 if (myRank == rootRank) {
356
357 // Open the file
358 in = Teuchos::RCP<std::ifstream>(new std::ifstream(filename, std::ios::in | std::ios::binary));
359
360 // Read number of vertices and number of edges
361 in->read((char *)&globalNumRows, sizeof(global_ordinal_type));
362 in->read((char *)&globalNumNonzeros, sizeof(global_ordinal_type));
363
364 TEUCHOS_TEST_FOR_EXCEPTION(globalNumRows <= 0 || globalNumNonzeros <= 0, std::invalid_argument,
365 "Global number of rows or nonzeros have nonpositive value." << globalNumRows << " " << globalNumNonzeros << " " << sizeof(global_ordinal_type) );
366 }
367
368 broadcast (*pComm, rootRank, 1, &globalNumRows);
369 broadcast (*pComm, rootRank, 1, &globalNumNonzeros);
370
371 global_ordinal_type *rowPtr = 0;
372 global_ordinal_type *colInd = 0;
373
374 if (myRank == rootRank) {
375
376 rowPtr = new global_ordinal_type[globalNumRows+1];
377 colInd = new global_ordinal_type[globalNumNonzeros];
378
379 in->read((char*)rowPtr, sizeof(global_ordinal_type)*(globalNumRows+1));
380 in->read((char*)colInd, sizeof(global_ordinal_type)*(globalNumNonzeros));
381
382 }
383
384
385 Teuchos::RCP<const map_type> pRowMap = Teuchos::rcp (new map_type (static_cast<Tpetra::global_size_t> (globalNumRows),
386 static_cast<global_ordinal_type> (0),
387 pComm, Tpetra::GloballyDistributed));
388
389 Teuchos::RCP<const map_type> pRangeMap = Teuchos::rcp (new map_type (static_cast<Tpetra::global_size_t> (globalNumRows),
390 static_cast<global_ordinal_type> (0),
391 pComm, Tpetra::GloballyDistributed));
392
393 Teuchos::RCP<const map_type> pDomainMap = pRangeMap;
394
395 Teuchos::ArrayView<const global_ordinal_type> myRows = pRowMap->getLocalElementList ();
396 const size_t myNumRows = myRows.size ();
397
398 Teuchos::ArrayRCP<size_t> myNumEntriesPerRow(myNumRows);
399 Teuchos::ArrayRCP<size_t> myRowPtr;
400 Teuchos::ArrayRCP<global_ordinal_type> myColInd;
401 Teuchos::ArrayRCP<scalar_type> myValues;
402
403
404 distribute<global_ordinal_type, local_ordinal_type, scalar_type, map_type>(myNumEntriesPerRow, myRowPtr, myColInd, myValues, pRowMap, rowPtr, colInd, debug);
405 pComm->barrier();
406
407 if (debug && myRank == rootRank) {
408 std::cout << "-- Inserting matrix entries on each processor";
409 if (callFillComplete) {
410 std::cout << " and calling fillComplete()";
411 }
412 std::cout << std::endl;
413 }
414
415 // get the colIds
416 std::vector<bool> mark(globalNumRows, false);
417 size_t myNumEntries = myRowPtr[myNumRows];
418 for(size_t i = 0; i < myNumEntries; i++)
419 mark[myColInd[i]] = true;
420
421 local_ordinal_type myNumCols = 0;
422 for(global_ordinal_type i = 0; i < globalNumRows; i++)
423 if(mark[i] == true)
424 myNumCols++;
425
426 Kokkos::View<global_ordinal_type*, typename node_type::memory_space> myColGIDs("myColGIDs", myNumCols);
427 auto myColGIDs_host = Kokkos::create_mirror_view(Kokkos::HostSpace(), myColGIDs);
428
429 myNumCols = 0;
430 for(global_ordinal_type i = 0; i < globalNumRows; i++)
431 if(mark[i] == true) {
432 myColGIDs_host(myNumCols)= i;
433 myNumCols++;
434 };
435
436 Kokkos::deep_copy(myColGIDs, myColGIDs_host);
437
438 Teuchos::RCP<const map_type> pColumnMap;
439 Tpetra::Details::makeColMap(pColumnMap, pDomainMap, myColGIDs);
440
441 std::vector<local_ordinal_type> map(globalNumRows);
442 for(global_ordinal_type i = 0; i < globalNumRows; i++) {
443 if(mark[i] == true)
444 map[i] = pColumnMap->getLocalElement(i);
445 }
446
447 Teuchos::ArrayRCP<local_ordinal_type> myLclColInd(myNumEntries);
448 for(size_t i = 0; i < myNumEntries; i++)
449 myLclColInd[i] = map[myColInd[i]];
450
451 local_ordinal_type *cur = myLclColInd.getRawPtr();
452
453 for(size_t i = 0; i < myNumRows; i++) {
454 size_t start = myRowPtr[i];
455 size_t end = myRowPtr[i+1];
456
457 std::sort(&cur[start], &cur[end]);
458 }
459
460 Teuchos::RCP<crs_graph_type> graph(new crs_graph_type(pRowMap, pColumnMap, myRowPtr, myLclColInd));
461 graph->fillComplete(pDomainMap, pRangeMap);
462
463 Kokkos::View<scalar_type*, typename node_type::memory_space> values("values", myNumEntries);
464 Kokkos::deep_copy(values, 1.0);
465
466 Teuchos::RCP<crs_matrix_type> pMatrix (new crs_matrix_type(graph, values));
467 pMatrix->fillComplete(pDomainMap, pRangeMap);
468
469 pComm->barrier();
470 if (debug && myRank == rootRank) {
471 std::cout << "-- Done with fill complete." << std::endl;
472 }
473
474 if(myRank == rootRank) {
475 delete [] rowPtr;
476 delete [] colInd;
477 }
478
479 return pMatrix;
480}
481
482template <typename crs_matrix_type>
483Teuchos::RCP<crs_matrix_type>
484readMatrixFromBinaryFile(std::string filename, const Teuchos::RCP<const Teuchos::Comm<int>> pComm, bool binary=true, bool debug=false)
485{
486 return readBinaryFileFast<crs_matrix_type>(filename, pComm, true, debug);
487}
488
489#endif
490
Teuchos::RCP< crs_matrix_type > readBinaryFileFast(std::string filename, const Teuchos::RCP< const Teuchos::Comm< int > > pComm, bool callFillComplete=true, bool debug=false)
Teuchos::RCP< crs_matrix_type > readMatrixFromBinaryFile(std::string filename, const Teuchos::RCP< const Teuchos::Comm< int > > pComm, bool binary=true, bool debug=false)
void distribute(Teuchos::ArrayRCP< size_t > &myNumEntriesPerRow, Teuchos::ArrayRCP< size_t > &myRowPtr, Teuchos::ArrayRCP< global_ordinal_type > &myColInd, Teuchos::ArrayRCP< scalar_type > &myValues, const Teuchos::RCP< const map_type > &pRowMap, global_ordinal_type *rowPtr, global_ordinal_type *colInd, const bool debug=false)
Teuchos::RCP< crs_matrix_type > readBinaryFile(std::string filename, const Teuchos::RCP< const Teuchos::Comm< int > > pComm, bool callFillComplete=true, bool debug=false)