40#include <parallel/algorithm>
41#include <parallel/numeric>
44#include "usort/parUtils.h"
48template <
class IT,
class NT>
53template <
class IT,
class NT>
58template <
class IT,
class NT>
63template <
class IT,
class NT>
69template <
class IT,
class NT>
81template <
class IT,
class NT>
89template <
class IT,
class NT>
90template <
typename _UnaryOperation>
96 std::vector<IT>().swap(ind);
97 std::vector<NT>().swap(num);
104 num.push_back(
rhs.arr[i]);
112template <
class IT,
class NT>
123#pragma omp parallel for
130#if defined(GNU_PARALLEL) && defined(_OPENMP)
144 ind.push_back(
itr->first);
145 num.push_back(
itr->second);
150 num.back() +=
itr->second;
182template <
class IT,
class NT>
187 std::vector<IT>().swap(ind);
188 std::vector<NT>().swap(num);
194 num.push_back(
rhs.arr[i]);
208template <
class IT,
class NT>
217 if(inds.TotalLength() !=
vals.TotalLength())
219 SpParHelper::Print(
"Index and value vectors have different sizes, FullyDistSpVec() fails !");
228 SpParHelper::Print(
"At least one index is greater than globallen, FullyDistSpVec() fails !");
235 int nprocs = commGrid->GetSize();
236 int * rdispls =
new int[
nprocs];
239 int * sdispls =
new int[
nprocs];
256 for(
int i=0; i<
nprocs-1; ++i)
258 sdispls[i+1] = sdispls[i] +
sendcnt[i];
259 rdispls[i+1] = rdispls[i] +
recvcnt[i];
267 int *count =
new int[
nprocs]();
294 std::vector< std::pair<IT,NT> >
tosort;
314 ind.push_back(
itr->first);
315 num.push_back(
itr->second);
320 num.back() +=
itr->second;
328template <
class IT,
class NT>
329template <
typename _Predicate>
342 found.arr.push_back(num[i]);
350 found.glen = std::accumulate(dist, dist+
nprocs,
static_cast<IT>(0));
367 int * sdispls =
new int[
nprocs];
368 int * rdispls =
new int[
nprocs];
371 for(
int i=0; i<
nprocs-1; ++i)
373 sdispls[i+1] = sdispls[i] +
sendcnt[i];
374 rdispls[i+1] = rdispls[i] +
recvcnt[i];
392template <
class IT,
class NT>
393template <
typename _Predicate>
415 found.glen = std::accumulate(dist, dist+
nprocs,
static_cast<IT>(0));
432 int * sdispls =
new int[
nprocs];
433 int * rdispls =
new int[
nprocs];
436 for(
int i=0; i<
nprocs-1; ++i)
438 sdispls[i+1] = sdispls[i] +
sendcnt[i];
439 rdispls[i+1] = rdispls[i] +
recvcnt[i];
455template <
class IT,
class NT>
463template <
class IT,
class NT>
472 typename std::vector<IT>::const_iterator
it = std::lower_bound(ind.begin(), ind.end(),
locind);
475 val = num[
it-ind.begin()];
490template <
class IT,
class NT>
497 typename std::vector<IT>::const_iterator
it = std::lower_bound(ind.begin(), ind.end(),
locind);
501 val = num[
it-ind.begin()];
510template <
class IT,
class NT>
520 typename std::vector<IT>::iterator
iter = std::lower_bound(ind.begin(), ind.end(),
locind);
521 if(
iter == ind.end())
530 num.insert(num.begin() + (
iter-ind.begin()), numx);
535 *(num.begin() + (
iter-ind.begin())) = numx;
540template <
class IT,
class NT>
547 typename std::vector<IT>::iterator
iter = std::lower_bound(ind.begin(), ind.end(),
locind);
550 num.erase(num.begin() + (
iter-ind.begin()));
564template <
class IT,
class NT>
571 std::unordered_map<IT, IT>
revr_map;
580 if(
ri.arr[i] >= glen ||
ri.arr[i] < 0)
596 revr_map.insert(
typename std::unordered_map<IT, IT>::value_type(
locind, i));
600 int * sdispls =
new int[
nprocs];
601 for(
int i=0; i<
nprocs; ++i)
604 int * rdispls =
new int[
nprocs];
610 for(
int i=0; i<
nprocs-1; ++i)
612 sdispls[i+1] = sdispls[i] +
sendcnt[i];
613 rdispls[i+1] = rdispls[i] +
recvcnt[i];
618 for(
int i=0; i<
nprocs; ++i)
621 std::vector<IT>().swap(
data_req[i]);
633 for(
int i=0; i<
nprocs; ++i)
640 for(
int j = rdispls[i];
j < rdispls[i] +
recvcnt[i]; ++
j)
659 for(
int i=0; i<
nprocs; ++i)
664 for(
int j=sdispls[i];
j< sdispls[i]+
sendcnt[i]; ++
j)
675template <
class IT,
class NT>
688template <
class IT,
class NT>
691 std::iota(num.begin(), num.end(), NnzUntil() + first);
695template <
class IT,
class NT>
768template <
class IT,
class NT>
773 if(getnnz()==0)
return temp;
774 IT nnz = getlocnnz();
775 std::pair<NT,IT> *
vecpair =
new std::pair<NT,IT>[nnz];
788#pragma omp parallel for
790 for(
IT i=0; i< nnz; ++i)
799 temp.num.resize(nnz);
800 temp.ind.resize(nnz);
803#pragma omp parallel for
805 for(
IT i=0; i< nnz; ++i)
888template <
class IT,
class NT>
889template <
typename _BinaryOperation >
899 size_t locvec = num.size();
901 for(
size_t i=0; i<
locvec; ++i)
905 double range =
static_cast<double>(
myhash) *
static_cast<double>(glen);
906 NT mapped =
range /
static_cast<double>(std::numeric_limits<uint64_t>::max());
913 int * sdispls =
new int[
nprocs];
914 for(
int i=0; i<
nprocs; ++i)
917 int * rdispls =
new int[
nprocs];
922 for(
int i=0; i<
nprocs-1; ++i)
924 sdispls[i+1] = sdispls[i] +
sendcnt[i];
925 rdispls[i+1] = rdispls[i] +
recvcnt[i];
928 for(
int i=0; i<
nprocs; ++i)
931 std::vector<NT>().swap(
datsent[i]);
934 for(
int i=0; i<
nprocs; ++i)
937 std::vector<IT>().swap(
indsent[i]);
948 std::vector< std::pair<NT,IT> >
tosort;
950 for(
int i=0; i<
nprocs; ++i)
952 for(
int j = rdispls[i];
j < rdispls[i] +
recvcnt[i]; ++
j)
960 typename std::vector< std::pair<NT,IT> >::iterator
last;
966 for(
typename std::vector< std::pair<NT,IT> >::iterator
itr =
tosort.begin();
itr !=
last; ++
itr)
976 for(
int i=0; i<
nprocs-1; ++i)
978 sdispls[i+1] = sdispls[i] +
sendcnt[i];
979 rdispls[i+1] = rdispls[i] +
recvcnt[i];
982 for(
int i=0; i<
nprocs; ++i)
985 std::vector<NT>().swap(
datback[i]);
988 for(
int i=0; i<
nprocs; ++i)
991 std::vector<IT>().swap(
indback[i]);
1005 std::vector< std::pair<IT,NT> >
back2sort;
1006 for(
int i=0; i<
nprocs; ++i)
1008 for(
int j = rdispls[i];
j < rdispls[i] +
recvcnt[i]; ++
j)
1027template <
class IT,
class NT>
1028template <
typename _BinaryOperation >
1034template <
class IT,
class NT>
1039 if(glen !=
rhs.glen)
1041 std::cerr <<
"Vector dimensions don't match for addition\n";
1047 std::vector< IT >
nind;
1048 std::vector< NT >
nnum;
1056 if(ind[i] >
rhs.ind[
j])
1061 else if(ind[i] <
rhs.ind[
j])
1063 nind.push_back( ind[i] );
1064 nnum.push_back( num[i++] );
1068 nind.push_back( ind[i] );
1069 nnum.push_back( num[i++] +
rhs.num[
j++] );
1074 nind.push_back( ind[i] );
1075 nnum.push_back( num[i++] );
1087 typename std::vector<NT>::iterator
it;
1088 for(
it = num.begin();
it != num.end(); ++
it)
1093template <
class IT,
class NT>
1098 if(glen !=
rhs.glen)
1100 std::cerr <<
"Vector dimensions don't match for addition\n";
1105 std::vector< IT >
nind;
1106 std::vector< NT >
nnum;
1114 if(ind[i] >
rhs.ind[
j])
1117 nnum.push_back( -
static_cast<NT>(
rhs.num[
j++]) );
1119 else if(ind[i] <
rhs.ind[
j])
1121 nind.push_back( ind[i] );
1122 nnum.push_back( num[i++] );
1126 nind.push_back( ind[i] );
1127 nnum.push_back( num[i++] -
rhs.num[
j++] );
1132 nind.push_back( ind[i] );
1133 nnum.push_back( num[i++] );
1152template <
class IT,
class NT>
1153template <
typename _BinaryOperation>
1159 for(
int i=0; i<
nprocs; ++i)
1163 int * sdispls =
new int[
nprocs]();
1164 int * rdispls =
new int[
nprocs]();
1172 for(
int i=0; i<
nprocs; ++i)
1174 std::copy(data[i].begin(), data[i].end(),
senddata+sdispls[i]);
1175 std::vector< std::pair<IT,NT> >().
swap(data[i]);
1194 if(ind.back() ==
recvdata[i].first)
1207template <
class IT,
class NT>
1208template <
typename _BinaryOperation>
1221 std::cout <<
"File failed to open\n";
1228 std::cout <<
"Total number of nonzeros expected across all processors is " <<
gnnz << std::endl;
1244 std::cout <<
"File is " <<
file_size <<
" bytes" << std::endl;
1259 std::vector< std::vector < std::pair<IT,NT> > > data(
nprocs);
1261 std::vector<std::string>
lines;
1276 std::stringstream
ss(*
itr);
1290 std::stringstream
ss(*
itr);
1300#ifdef COMBBLAS_DEBUG
1302 std::cout <<
"Reading finished. Total number of entries read across all processors is " <<
allentriesread << std::endl;
1305 SparseCommon(data,
BinOp);
1308template <
class IT,
class NT>
1309template <
class HANDLER>
1317 std::stringstream
ss;
1348 std::string
text =
ss.str();
1358 std::ofstream
ofs(
filename.c_str(), std::ios::binary | std::ios::out);
1359#ifdef COMBBLAS_DEBUG
1360 std::cout <<
"Creating file with " <<
bytestotal <<
" bytes" << std::endl;
1375#ifdef COMBBLAS_DEBUG
1376 std::cout <<
"File is actually " <<
st.st_size <<
" bytes seen from process " << myrank << std::endl;
1383 printf(
"COMBBLAS: Vector output file %s failed to open at process %d\n",
filename.c_str(), myrank);
1395template <
class IT,
class NT>
1396template <
class HANDLER>
1405 for (
int i=0; i<
neighs; ++i)
1484 std::fill_n(
curptrs,
neighs, std::numeric_limits<int>::max());
1502 if(
recvcount == std::numeric_limits<int>::max())
1527template <
class IT,
class NT>
1528template <
class HANDLER>
1537 char _fn[] =
"temp_fullydistspvec";
1549 dist[
rank] = getlocnnz();
1569 char native[] =
"native";
1572 int count = ind.size();
1574 for(
int i=0; i<count; ++i)
1597 FILE *
f =
fopen(
"temp_fullydistspvec",
"r");
1600 std::cerr <<
"Problem reading binary input file\n";
1609 for(
int i=0; i<
nprocs; ++i)
1612 if (
fread(data,
dsize, dist[i],
f) <
static_cast<size_t>(dist[i]))
1614 std::cout <<
"fread 660 failed! attempting to continue..." << std::endl;
1618 outfile <<
"Elements stored on proc " << i <<
":" << std::endl;
1620 for (
int j = 0;
j < dist[i];
j++)
1622 outfile << data[
j].ind+1 <<
"\t1\t";
1629 remove(
"temp_fullydistspvec");
1637template <
class IT,
class NT>
1638template <
typename _Predicate>
1648template <
class IT,
class NT>
1649template <
typename _BinaryOperation>
1661template <
class IT,
class NT>
1662template <
typename OUT,
typename _BinaryOperation,
typename _UnaryOperation>
1670 typename std::vector< NT >::const_iterator
iter = num.begin();
1673 while (
iter < num.end())
1685template <
class IT,
class NT>
1690 std::cout <<
"As a whole, " <<
vectorname <<
" has: " <<
nznz <<
" nonzeros and length " << glen << std::endl;
1693template <
class IT,
class NT>
1702 char tfilename[32] =
"temp_fullydistspvec";
1706 dist[
rank] = getlocnnz();
1727 int count = ind.size();
1729 for(
int i=0; i<count; ++i)
1742 FILE *
f =
fopen(
"temp_fullydistspvec",
"r");
1745 std::cerr <<
"Problem reading binary input file\n";
1751 for(
int i=0; i<
nprocs; ++i)
1754 if (
fread(data,
dsize, dist[i],
f) <
static_cast<size_t>(dist[i]))
1756 std::cout <<
"fread 802 failed! attempting to continue..." << std::endl;
1759 std::cout <<
"Elements stored on proc " << i <<
": {";
1760 for (
int j = 0;
j < dist[i];
j++)
1762 std::cout <<
"(" << data[
j].ind <<
"," << data[
j].num <<
"), ";
1764 std::cout <<
"}" << std::endl;
1767 remove(
"temp_fullydistspvec");
1774template <
class IT,
class NT>
1782template <
class IT,
class NT>
1786 std::copy(inds, inds+count, ind.data());
1787 std::copy(inds, inds+count, num.data());
1900template <
class IT,
class NT>
1907 std::cout <<
"Sparse vector has entries (" <<
max_entry <<
") larger than requested global vector length " <<
globallen << std::endl;
1913 int * rdispls =
new int[
nprocs+1];
1916 int * sdispls =
new int[
nprocs+1];
1921#pragma omp parallel for
1939 for(
int i=0; i<
nprocs; ++i)
1941 sdispls[i+1] = sdispls[i] +
sendcnt[i];
1942 rdispls[i+1] = rdispls[i] +
recvcnt[i];
1949 int *count =
new int[
nprocs]();
1951#pragma omp parallel for
1964 datbuf[id] = ind[i] + LengthUntil();
1980 std::vector< std::pair<IT,NT> >
tosort;
1983#pragma omp parallel for
1992#if defined(GNU_PARALLEL) && defined(_OPENMP)
2003 for(
typename std::vector<std::pair<IT,NT>>::iterator
itr =
tosort.begin();
itr !=
tosort.end(); ++
itr)
2025template <
class IT,
class NT>
2026template <
typename _BinaryOperationIdx,
typename _BinaryOperationVal,
typename _BinaryOperationDuplicate>
2036 for(
size_t k=0; k < num.size(); ++k)
2045 std::cout <<
"Sparse vector has entries (" <<
globalmax <<
") larger than requested global vector length " <<
globallen << std::endl;
2053 int * rdispls =
new int[
nprocs+1];
2056 int * sdispls =
new int[
nprocs+1];
2061#pragma omp parallel for
2081 for(
int i=0; i<
nprocs; ++i)
2083 sdispls[i+1] = sdispls[i] +
sendcnt[i];
2084 rdispls[i+1] = rdispls[i] +
recvcnt[i];
2090 int *count =
new int[
nprocs]();
2092#pragma omp parallel for
2122 std::vector< std::pair<IT,NT> >
tosort;
2125#pragma omp parallel for
2134#if defined(GNU_PARALLEL) && defined(_OPENMP)
2145 for(
typename std::vector<std::pair<IT,NT>>::iterator
itr =
tosort.begin();
itr !=
tosort.end(); )
2147 IT ind =
itr->first;
2148 NT val =
itr->second;
2170template <
class IT,
class NT>
2171template <
typename _BinaryOperationIdx,
typename _BinaryOperationVal>
2182 for(
size_t k=0; k < num.size(); ++k)
2191 std::cout <<
"Sparse vector has entries (" <<
globalmax <<
") larger than requested global vector length " <<
globallen << std::endl;
2199 int * rdispls =
new int[
nprocs+1];
2202 int * sdispls =
new int[
nprocs+1];
2207#pragma omp parallel for
2225 for(
int i=0; i<
nprocs; ++i)
2240 for(
int i=0; i<
nprocs; ++i)
2242 sdispls[i+1] = sdispls[i] +
sendcnt[i];
2243 rdispls[i+1] = rdispls[i] +
recvcnt[i];
2249 for(
int i=0; i<
nprocs; ++i)
2263 int *count =
new int[
nprocs]();
2265#pragma omp parallel for
2293 for(
int i=0; i<
nprocs; ++i)
2316 std::vector< std::pair<IT,NT> >
tosort;
2319#pragma omp parallel for
2328#if defined(GNU_PARALLEL) && defined(_OPENMP)
2339 for(
typename std::vector<std::pair<IT,NT>>::iterator
itr =
tosort.begin();
itr !=
tosort.end(); ++
itr)
2356template <
typename IT,
typename NT>
2357template <
typename NT1,
typename _UnaryOperation>
2362 if(TotalLength() !=
denseVec.TotalLength())
2364 std::ostringstream
outs;
2365 outs <<
"Vector dimensions don't match (" << TotalLength() <<
" vs " <<
denseVec.TotalLength() <<
") for Select\n";
2389 std::ostringstream
outs;
2390 outs <<
"Grids are not comparable for Select" << std::endl;
2398template <
typename IT,
typename NT>
2399template <
typename NT1>
2404 if(TotalLength() != other.TotalLength())
2406 std::ostringstream
outs;
2407 outs <<
"Vector dimensions don't match (" << TotalLength() <<
" vs " << other.TotalLength() <<
") for Select\n";
2420 if(other.ind[
j] == ind[i])
2424 else if(other.ind[
j] > ind[i])
2427 num[k++] = num[i++];
2434 num[k++] = num[i++];
2443 std::ostringstream
outs;
2444 outs <<
"Grids are not comparable for Select" << std::endl;
2452template <
typename IT,
typename NT>
2453template <
typename NT1,
typename _UnaryOperation,
typename _BinaryOperation>
2458 if(TotalLength() !=
denseVec.TotalLength())
2460 std::ostringstream
outs;
2461 outs <<
"Vector dimensions don't match (" << TotalLength() <<
" vs " <<
denseVec.TotalLength() <<
") for Select\n";
2485 std::ostringstream
outs;
2486 outs <<
"Grids are not comparable for Select" << std::endl;
2515template <
class IT,
class NT>
2516template <
typename _UnaryOperation>
2521 std::ostringstream
outs;
2522 outs <<
"Grids are not comparable for Filter" << std::endl;
2530 int * rdispls =
new int[
nprocs];
2536 for(
int i=0; i<
nprocs-1; ++i)
2538 rdispls[i+1] = rdispls[i] +
recvcnt[i];
2544#pragma omp parallel for
2565#if defined(GNU_PARALLEL) && defined(_OPENMP)
2575 for(
IT i=0; i<num.size(); i++)
std::shared_ptr< CommGrid > commGrid
FullyDistSpVec< IT, NT > & operator=(const FullyDistSpVec< IT, NT > &rhs)
void Select(const FullyDistVec< IT, NT1 > &denseVec, _UnaryOperation unop)
FullyDistSpVec< IT, IT > sort()
sort the vector itself, return the permutation vector (0-based)
std::ifstream & ReadDistribute(std::ifstream &infile, int master, HANDLER handler)
Totally obsolete version that only accepts an ifstream object and ascii files.
FullyDistSpVec< IT, NT > & operator-=(const FullyDistSpVec< IT, NT > &rhs)
NT Reduce(_BinaryOperation __binary_op, NT init) const
FullyDistSpVec< IT, NT > Uniq(_BinaryOperation __binary_op, MPI_Op mympiop)
FullyDistVec< IT, NT > FindVals(_Predicate pred) const
void nziota(NT first)
iota over existing nonzero entries
void ParallelWrite(const std::string &filename, bool onebased, HANDLER handler, bool includeindices=true, bool includeheader=false)
void FilterByVal(FullyDistSpVec< IT, IT > Selector, _UnaryOperation __unop, bool filterByIndex)
FullyDistSpVec< IT, NT > Invert(IT globallen)
void SelectApply(const FullyDistVec< IT, NT1 > &denseVec, _UnaryOperation __unop, _BinaryOperation __binop)
IT Count(_Predicate pred) const
Return the number of elements for which pred is true.
FullyDistVec< IT, NT > operator()(const FullyDistVec< IT, IT > &ri) const
SpRef (expects ri to be 0-based)
void ParallelRead(const std::string &filename, bool onebased, _BinaryOperation BinOp)
friend class FullyDistSpVec
FullyDistVec< IT, IT > FindInds(_Predicate pred) const
void SaveGathered(std::ofstream &outfile, int master, HANDLER handler, bool printProcSplits=false)
IT NnzUntil() const
Returns the number of nonzeros until this processor.
void BulkSet(IT inds[], int count)
NT GetLocalElement(IT indx)
FullyDistSpVec< IT, NT > & operator+=(const FullyDistSpVec< IT, NT > &rhs)
void PrintInfo(std::string vecname) const
void Setminus(const FullyDistSpVec< IT, NT1 > &other)
void iota(IT globalsize, NT first)
void SetElement(IT indx, NT numx)
Indexing is performed 0-based.
void stealFrom(FullyDistSpVec< IT, NT > &victim)
FullyDistSpVec< IT, NT > InvertRMA(IT globallen, _BinaryOperationIdx __binopIdx, _BinaryOperationVal __binopVal)
static void iota(_ForwardIter __first, _ForwardIter __last, T __val)
static bool FetchBatch(MPI_File &infile, MPI_Offset &curpos, MPI_Offset end_fpos, bool firstcall, std::vector< std::string > &lines, int myrank)
static std::vector< std::pair< KEY, VAL > > KeyValuePSort(std::pair< KEY, VAL > *array, IT length, IT *dist, const MPI_Comm &comm)
static void Print(const std::string &s)
bool is_sorted(_ForwardIterator __first, _ForwardIterator __last)
void MurmurHash3_x64_64(const void *key, int len, uint32_t seed, void *out)
unsigned __int64 uint64_t