package water.rapids;
import water.H2O;
import water.MRTask;
import water.fvec.Chunk;
import water.util.AtomicUtils;
// Now find groups ...
// Find group sizes when we know the number of groups ...
// long groups[][] = new long[256][]; // at most MAXVEC groups per radix, currently
//// new helper class A extend MRTask. In its reduce it'll get another A. Make another class B extends ICED that wraps a bunch of long arrays (like I have now).
//// A contains B as a member. The long arrays are easy to serialize automatically. As you reduce two A's, do with the two B's. 'this' in the reduce will have the target A.
//// B gets initialized in the setupLocal() of A on each node. Check in A's reduce that the two B's have different pointers else return. See Arno's DeepLearningTask;
//// DeepLearningModelInfo is his B.
class assignG extends H2O.H2OCountedCompleter<assignG> {
private static final int MAXVECLONG = 134217728, MAXVECBYTE = 1073741824;
long _gOut[][]; // wide writing to here, but thread safe due to each location written once only
long _groups[]; // the group sizes
long _nGroup; // length of _groups because we over-allocated it
long _o[][]; // the order for this segment
long _firstGroupNum;
assignG(long gOut[][], long groups[], long nGroup, long firstGroupNum, long o[][]) {
_gOut = gOut;
_groups = groups;
_nGroup = nGroup;
_firstGroupNum = firstGroupNum;
_o = o;
}
@Override
public void compute2() {
int oi = 0, batch=0;
long _ob[] = _o[batch];
long gOutBatch[] = _gOut[batch];
for (int i=0; i<_nGroup; i++) {
for (int j = 0; j < _groups[i]; j++) {
long target = _ob[oi++];
assert target < MAXVECLONG;
gOutBatch[(int)(target)] = _firstGroupNum+i;
if (oi == MAXVECLONG) {
assert false;
_ob = _o[++batch];
oi -= MAXVECLONG;
}
}
}
tryComplete();
}
}
/*
long nGroups = 0;
for (int i = 0; i < 257; i++) {
long tmp = nGroup[i];
nGroup[i] = nGroups;
nGroups += tmp;
}
System.out.println("Time to recursive radix: " + (System.nanoTime() - t0) / 1e9 ); t0 = System.nanoTime();
System.out.println("Total groups found: " + nGroups);
if (!retGrp) return;
// We now have o and x that bmerge() needs
long nrow = DF.numRows();
long g[][] = new long[(int)(1 + nrow / MAXVECLONG)][];
int c;
for (c=0; c<nrow/MAXVECLONG; c++) {
g[c] = new long[MAXVECLONG];
}
g[c] = new long[(int)(nrow % MAXVECLONG)];
fs = new Futures();
for (int i=0; i<256; i++) {
if (reduceHist[i] > 0)
fs.add(H2O.submitTask(new assignG(g, groups[i], nGroup[i+1]-nGroup[i], nGroup[i], o[i])));
// reuse the x vector we allocated before to store the group numbers. i.e. a perfect and ordered hash, stored alongside table
}
fs.blockForPending();
System.out.println("Time to assign group index (length nrows): " + (System.nanoTime() - t0) / 1e9 ); t0 = System.nanoTime();
//Vec res = Vec.makeZero(nGroups); // really slow to assign to
double res[] = new double[(int)nGroups];
new runSum(g, res).doAll(toSum);
// TO DO: Create final frame with 3 columns
System.out.println("Time to sum column: " + (System.nanoTime() - t0) / 1e9 );
System.out.println("Total time: " + (System.nanoTime() - t00) / 1e9);
for (int i = 0; i < 5; i++) System.out.format("%7.0f\n", res[i]);
System.out.println("---");
for (int i = 4; i >= 0; i--) System.out.format("%7.0f\n", res[(int)nGroups-i-1]);
*/
/*
System.out.println("Head and tail:");
int head=10, done=0, batch = -1;
while (done < head) {
while (o[++batch] == null) ;
for (int i = 0; done < head && i < o[batch][0].length; i++)
System.out.format("%7d: %16d\n", done++, vec.at8(o[batch][0][i]));
}
System.out.println("--------");
batch = 256;
done = 0;
while (done < head) {
while (o[--batch] == null) ;
for (int i = o[batch][0].length - 1; done < head && i >= 0; i--)
System.out.format("%7d: %16d\n", vec.length() - ++done, vec.at8(o[batch][0][i]));
}
System.out.print("\n");
*/
/*
void cummulate(long x[][], long a, long b) {
long rollSum = 0;
for (int j=0; j<b; j++)
for (int i=0; i<a; i++) {
long tmp = x[i][j];
x[i][j] = rollSum;
rollSum += tmp;
}
}
*/
class runSum extends MRTask<runSum> {
private static final int MAXVECLONG = 134217728, MAXVECBYTE = 1073741824;
long _g[];
double _res[];
runSum(long g[][], double res[]) { _g = g[0]; _res = res;}
@Override public void map(Chunk chk) {
// TODO: if spans 2 MAXVEC in g. Currently hard coded to g[0]
int j = (int)chk.start();
for (int r=0; r<chk._len; r++) {
AtomicUtils.DoubleArray.add(_res, (int) _g[j++], chk.at8(r));
}
}
}