void bfs_stinger (const struct stinger *G, const int64_t nv, const int64_t ne, const int64_t startV, int64_t * marks, const int64_t numSteps, int64_t * Q, int64_t * QHead, int64_t * neighbors) { int64_t j, k, s; int64_t nQ, Qnext, Qstart, Qend; int64_t w_start; MTA ("mta assert nodep") for (j = 0; j < nv; j++) { marks[j] = 0; } s = startV; /* Push node s onto Q and set bounds for first Q sublist */ Q[0] = s; Qnext = 1; nQ = 1; QHead[0] = 0; QHead[1] = 1; marks[s] = 1; PushOnStack: /* Push nodes onto Q */ /* Execute the nested loop for each node v on the Q AND for each neighbor w of v */ Qstart = QHead[nQ - 1]; Qend = QHead[nQ]; w_start = 0; MTA ("mta assert no dependence") MTA ("mta block dynamic schedule") for (j = Qstart; j < Qend; j++) { int64_t v = Q[j]; size_t d; size_t deg_v = stinger_outdegree (G, v); int64_t my_w = stinger_int64_fetch_add (&w_start, deg_v); stinger_gather_typed_successors (G, 0, v, &d, &neighbors[my_w], deg_v); assert (d == deg_v); MTA ("mta assert nodep") for (k = 0; k < deg_v; k++) { int64_t d, w, l; w = neighbors[my_w + k]; /* If node has not been visited, set distance and push on Q */ if (stinger_int64_fetch_add (marks + w, 1) == 0) { Q[stinger_int64_fetch_add (&Qnext, 1)] = w; } } } if (Qnext != QHead[nQ] && nQ < numSteps) { nQ++; QHead[nQ] = Qnext; goto PushOnStack; } }
void update_rates(stinger_registered_alg * a, int64_t nv, double * vel, double * accel, double vel_keep, double accel_keep) { int64_t * count = calloc(nv, sizeof(int64_t)); OMP("omp parallel for") for(int64_t i = 0; i < a->num_insertions; i++) { stinger_int64_fetch_add(count + a->insertions[i].source,1); stinger_int64_fetch_add(count + a->insertions[i].destination,1); } OMP("omp parallel for") for(int64_t i = 0; i < a->num_deletions; i++) { stinger_int64_fetch_add(count + a->deletions[i].source,1); stinger_int64_fetch_add(count + a->deletions[i].destination,1); } OMP("omp parallel for") for(int64_t v = 0; v < nv; v++) { accel[v] = (accel_keep * accel[v]) + (1 - accel_keep) * (count[v] - vel[v]); vel[v] = (vel_keep * vel[v]) + (1 - vel_keep) * count[v]; } free(count); }
int64_t st_conn_csr (const int64_t nv, const int64_t ne, const int64_t * off, const int64_t * ind, const int64_t * sources, const int64_t num, const int64_t numSteps) { int64_t k, x; int64_t *Q_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *marks_s_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *marks_t_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *QHead_big = (int64_t *) xmalloc (INC * 2 * numSteps * sizeof (int64_t)); int64_t *neighbors_big = (int64_t *) xmalloc (INC * ne * sizeof (int64_t)); int64_t count = 0; k = 0; MTA ("mta assert parallel") MTA ("mta loop future") for (x = 0; x < INC; x++) { int64_t *Q = Q_big + x * nv; int64_t *marks_s = marks_s_big + x * nv; int64_t *marks_t = marks_t_big + x * nv; int64_t *QHead = QHead_big + x * 2 * numSteps; int64_t *neighbors = neighbors_big + x * ne; for (int64_t claimedk = stinger_int64_fetch_add (&k, 2); claimedk < 2 * num; claimedk = stinger_int64_fetch_add (&k, 2)) { int64_t s = sources[claimedk]; int64_t t = sources[claimedk + 1]; bfs_csr (nv, ne, off, ind, s, marks_s, numSteps, Q, QHead); bfs_csr (nv, ne, off, ind, t, marks_t, numSteps, Q, QHead); int64_t local_count = 0; MTA ("mta assert nodep") for (int64_t j = 0; j < nv; j++) { if (marks_s[j] && marks_t[j]) stinger_int64_fetch_add (&local_count, 1); } if (local_count == 0) stinger_int64_fetch_add (&count, 1); } } free (neighbors_big); free (QHead_big); free (marks_t_big); free (marks_s_big); free (Q_big); return count; }
void bfs_csr (const int64_t nv, const int64_t ne, const int64_t * off, const int64_t * ind, const int64_t startV, int64_t * marks, const int64_t numSteps, int64_t * Q, int64_t * QHead) { int64_t j, k, s; int64_t nQ, Qnext, Qstart, Qend; MTA ("mta assert nodep") for (j = 0; j < nv; j++) { marks[j] = 0; } s = startV; /* Push node s onto Q and set bounds for first Q sublist */ Q[0] = s; Qnext = 1; nQ = 1; QHead[0] = 0; QHead[1] = 1; marks[s] = 1; PushOnStack: /* Push nodes onto Q */ /* Execute the nested loop for each node v on the Q AND for each neighbor w of v */ Qstart = QHead[nQ - 1]; Qend = QHead[nQ]; MTA ("mta assert no dependence") MTA ("mta block dynamic schedule") for (j = Qstart; j < Qend; j++) { int64_t v = Q[j]; int64_t myStart = off[v]; int64_t myEnd = off[v + 1]; MTA ("mta assert nodep") for (k = myStart; k < myEnd; k++) { int64_t d, w, l; w = ind[k]; /* If node has not been visited, set distance and push on Q */ if (stinger_int64_fetch_add (marks + w, 1) == 0) { Q[stinger_int64_fetch_add (&Qnext, 1)] = w; } } } if (Qnext != QHead[nQ] && nQ < numSteps) { nQ++; QHead[nQ] = Qnext; goto PushOnStack; } }
int64_t st_conn_stinger_source (const struct stinger * G, const int64_t nv, const int64_t ne, const int64_t from, const int64_t * sources, const int64_t num, const int64_t numSteps) { int64_t k; int64_t *Q = (int64_t *) xmalloc (nv * sizeof (int64_t)); int64_t *marks_s = (int64_t *) xmalloc (nv * sizeof (int64_t)); int64_t *marks_t = (int64_t *) xmalloc (nv * sizeof (int64_t)); int64_t *QHead = (int64_t *) xmalloc (2 * numSteps * sizeof (int64_t)); int64_t *neighbors = (int64_t *) xmalloc (ne * sizeof (int64_t)); int64_t count = 0; int64_t deg_s = stinger_outdegree (G, from); if (deg_s == 0) { return num; } bfs_stinger (G, nv, ne, from, marks_s, numSteps, Q, QHead, neighbors); for (k = 0; k < num; k++) { int64_t t = sources[k]; int64_t deg_t = stinger_outdegree (G, t); if (deg_t == 0) { stinger_int64_fetch_add (&count, 1); } else { bfs_stinger (G, nv, ne, t, marks_t, numSteps, Q, QHead, neighbors); int64_t local_count = 0; MTA ("mta assert nodep") for (int64_t j = 0; j < nv; j++) { if (marks_s[j] && marks_t[j]) stinger_int64_fetch_add (&local_count, 1); } if (local_count == 0) stinger_int64_fetch_add (&count, 1); } } free (neighbors); free (QHead); free (marks_t); free (marks_s); free (Q); return count; }
int64_t parallel_breadth_first_search (struct stinger * S, int64_t nv, int64_t source, int64_t * marks, int64_t * queue, int64_t * Qhead, int64_t * level) { for (int64_t i = 0; i < nv; i++) { level[i] = -1; marks[i] = 0; } int64_t nQ, Qnext, Qstart, Qend; /* initialize */ queue[0] = source; level[source] = 0; marks[source] = 1; Qnext = 1; /* next open slot in the queue */ nQ = 1; /* level we are currently processing */ Qhead[0] = 0; /* beginning of the current frontier */ Qhead[1] = 1; /* end of the current frontier */ Qstart = Qhead[nQ-1]; Qend = Qhead[nQ]; while (Qstart != Qend) { OMP ("omp parallel for") for (int64_t j = Qstart; j < Qend; j++) { STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, queue[j]) { int64_t d = level[STINGER_EDGE_DEST]; if (d < 0) { if (stinger_int64_fetch_add (&marks[STINGER_EDGE_DEST], 1) == 0) { level[STINGER_EDGE_DEST] = nQ; int64_t mine = stinger_int64_fetch_add(&Qnext, 1); queue[mine] = STINGER_EDGE_DEST; } } } STINGER_FORALL_EDGES_OF_VTX_END(); } Qstart = Qhead[nQ-1]; Qend = Qnext; Qhead[nQ++] = Qend; }
/** * @brief Perform a single source of the BC calculation per Brandes. * * Note that this follows the approach suggested by Green and Bader in which * parent lists are not maintained, but instead the neighbors are searched * to rediscover parents. * * Note also that found count will not include the source and that increments * to this array are handled atomically. * * Operations to the bc array are NOT ATOMIC * * @param S The STINGER graph * @param nv The maximum vertex ID in the graph plus one. * @param source The vertex from where this search will start. * @param bc The array into which the partial BCs will be added. * @param found_count An array to track how many times a vertex is found for normalization. */ void single_bc_search(stinger_t * S, int64_t nv, int64_t source, double * bc, int64_t * found_count) { int64_t * paths = (int64_t * )xcalloc(nv * 2, sizeof(int64_t)); int64_t * q = paths + nv; double * partial = (double *)xcalloc(nv, sizeof(double)); int64_t * d = (int64_t *)xmalloc(nv * sizeof(int64_t)); for(int64_t i = 0; i < nv; i ++) d[i] = -1; int64_t q_front = 1; int64_t q_rear = 0; q[0] = source; d[source] = 0; paths[source] = 1; while(q_rear != q_front) { int64_t v = q[q_rear++]; int64_t d_next = d[v] + 1; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { if(d[STINGER_EDGE_DEST] < 0) { d[STINGER_EDGE_DEST] = d_next; paths[STINGER_EDGE_DEST] = paths[v]; q[q_front++] = STINGER_EDGE_DEST; stinger_int64_fetch_add(found_count + STINGER_EDGE_DEST, 1); } else if(d[STINGER_EDGE_DEST] == d_next) { paths[STINGER_EDGE_DEST] += paths[v]; } } STINGER_FORALL_EDGES_OF_VTX_END(); } /* don't process source */ while(q_front > 1) { int64_t w = q[--q_front]; /* don't maintain parents, do search instead */ STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, w) { if(d[STINGER_EDGE_DEST] == (d[w] - 1)) { partial[STINGER_EDGE_DEST] += frac(paths[STINGER_EDGE_DEST],paths[w]) * (1 + partial[w]); } } STINGER_FORALL_EDGES_OF_VTX_END(); bc[w] += partial[w]; } free(d); free(partial); free(paths); }
int64_t st_conn_stinger (const struct stinger *G, const int64_t nv, const int64_t ne, const int64_t * sources, const int64_t num, const int64_t numSteps) { int64_t k, x; int64_t *Q_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *marks_s_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *marks_t_big = (int64_t *) xmalloc (INC * nv * sizeof (int64_t)); int64_t *QHead_big = (int64_t *) xmalloc (INC * 2 * numSteps * sizeof (int64_t)); int64_t *neighbors_big = (int64_t *) xmalloc (INC * ne * sizeof (int64_t)); int64_t count = 0; k = 0; x = 0; OMP ("omp parallel for") MTA ("mta assert parallel") MTA ("mta loop future") MTA ("mta assert nodep") MTA ("mta assert no alias") for (x = 0; x < INC; x++) { int64_t *Q = Q_big + x * nv; int64_t *marks_s = marks_s_big + x * nv; int64_t *marks_t = marks_t_big + x * nv; int64_t *QHead = QHead_big + x * 2 * numSteps; int64_t *neighbors = neighbors_big + x * ne; for (int64_t claimedk = stinger_int64_fetch_add (&k, 2); claimedk < 2 * num; claimedk = stinger_int64_fetch_add (&k, 2)) { int64_t s = sources[claimedk]; int64_t deg_s = stinger_outdegree (G, s); int64_t t = sources[claimedk + 1]; int64_t deg_t = stinger_outdegree (G, t); if (deg_s == 0 || deg_t == 0) { stinger_int64_fetch_add (&count, 1); } else { bfs_stinger (G, nv, ne, s, marks_s, numSteps, Q, QHead, neighbors); bfs_stinger (G, nv, ne, t, marks_t, numSteps, Q, QHead, neighbors); int64_t local_count = 0; MTA ("mta assert nodep") for (int64_t j = 0; j < nv; j++) { if (marks_s[j] && marks_t[j]) stinger_int64_fetch_add (&local_count, 1); } if (local_count == 0) stinger_int64_fetch_add (&count, 1); } } } free (neighbors_big); free (QHead_big); free (marks_t_big); free (marks_s_big); free (Q_big); return count; }