Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Makefile.common
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#set the following variables to absolute paths
CHARM_DIR = /Users/raghu/work/charm/charm
UNION_FIND_DIR = /Users/raghu/work/charm/unionFind/unionFind
CHARM_DIR = /Users/johnnychen/Documents/Projects/research/charm
UNION_FIND_DIR = /Users/johnnychen/Documents/Projects/research/unionfind
PREFIX_LIB_DIR = $(UNION_FIND_DIR)/prefixLib

#charmc options
ANCHOR= -DANCHOR_ALGO
#ANCHOR=
PROFILE= -DPROFILING
CHARMC = $(CHARM_DIR)/bin/charmc $(ANCHOR) $(PROFILE)
CHARMC = $(CHARM_DIR)/bin/charmc $(PROFILE) #$(ANCHOR)
OPTS = -std=c++11 -O3 -g
LD_OPTS =

Expand All @@ -16,4 +16,4 @@ PREFIX_LIBS = -L${PREFIX_LIB_DIR} -lprefix
PREFIX_INC = -I${PREFIX_LIB_DIR}

UNION_FIND_LIBS = -L${UNION_FIND_DIR} -lunionFind ${PREFIX_LIBS}
UNION_FIND_INC = -I${UNION_FIND_DIR} ${PREFIX_INC}
UNION_FIND_INC = -I${UNION_FIND_DIR} ${PREFIX_INC}
6 changes: 3 additions & 3 deletions examples/simple_graph/graph.C
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class TreePiece : public CBase_TreePiece {
// function that must be always defined by application
// return type -> std::pair<int, int>
// this specific logic assumes equal distribution of vertices across all tps
static std::pair<int, int> getLocationFromID(long int vid);
static std::pair<int, int> getLocationFromID(uint64_t vid);

void initializeLibVertices() {
// provide vertices data to library
Expand Down Expand Up @@ -203,11 +203,11 @@ TreePiece::getLocationFromID(long int vid) {
*/

std::pair<int, int>
TreePiece::getLocationFromID(long int vid) {
TreePiece::getLocationFromID(uint64_t vid) {
int chareIdx = (vid-1) % NUM_TREEPIECES;
int arrIdx = (vid-1) / NUM_TREEPIECES;
return std::make_pair(chareIdx, arrIdx);
}


#include "graph.def.h"
#include "graph.def.h"
2 changes: 1 addition & 1 deletion prefixLib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ CHARMC=/Users/raghu/work/charm/charm/bin/charmc $(OPTS)
all: libprefix.a

libprefix.a: prefixBalance.o
$(CHARMC) prefixBalance.o -o libprefix.a -language charm++
$(CHARMC) prefixBalance.o -o libprefix.a -language charm++ # -DCK_TEMPLATES_ONLY

prefixBalance.o : prefixBalance.C prefixBalance.def.h prefixBalance.decl.h
$(CHARMC) -c prefixBalance.C
Expand Down
12 changes: 11 additions & 1 deletion types.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ struct findBossData {
}
};

struct needBossData {
uint64_t arrIdx;
uint64_t senderID;

void pup(PUP::er &p) {
p|arrIdx;
p|senderID;
}
};

#ifdef ANCHOR_ALGO
struct anchorData {
uint64_t arrIdx;
Expand All @@ -26,7 +36,7 @@ struct anchorData {

struct shortCircuitData {
uint64_t arrIdx;
uint64_t grandparentID;
int64_t grandparentID;

void pup(PUP::er &p) {
p|arrIdx;
Expand Down
137 changes: 100 additions & 37 deletions unionFindLib.C
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,21 @@ static void register_merge_count_maps_reduction() {

// class function implementations

/**
* @brief registers a function that takes a vertexID and returns its location
*
* unionFindLib allows users to specify a vertexID scheme that suits their
* usecase, as long as it encodes the chare index of the vertex and array index
* of the vertex on the chare's myVertices field. This function registers the
* function provided by the user that achieves this decoding, so that the user's
* function may be used by unionFindLib for internal functionality
*
* @param gloc a function that takes a uint64_t vertexID and returns its chare
* index and local array index on that chare's myVertices field as
* a std::pair<int, int>
*/
void UnionFindLib::
registerGetLocationFromID(std::pair<int, int> (*gloc)(long int vid)) {
registerGetLocationFromID(std::pair<int, int> (*gloc)(uint64_t vid)) {
getLocationFromID = gloc;
}

Expand All @@ -58,35 +71,50 @@ register_phase_one_cb(CkCallback cb) {
CkStartQD(cb);
}

/**
* @brief Adds vertices to this union find chare
*
* Takes an array of unionFindVertex with vertex info populated (ID, etc.)
* and the length of that array, and stores locally the vertex info
* that should be associated with this union find chare.
*
* @param appVertices an array of unionFindVertex storing the vertices on the
* corresponding partition chare
* @param numVertices the number of vertices in the appVertices array
*/
void UnionFindLib::
initialize_vertices(unionFindVertex *appVertices, int numVertices) {
// local vertices corresponding to one treepiece in application
numMyVertices = numVertices;
myVertices = appVertices; // no need to do memcpy, array in same address space as app
/*myVertices = (unionFindVertex*)malloc(numVertices * sizeof(unionFindVertex));
memcpy(myVertices, appVertices, sizeof(unionFindVertex)*numVertices);*/
/*for (int i = 0; i < numMyVertices; i++) {
CkPrintf("[LibProxy %d] myVertices[%d] - vertexID: %ld, parent: %ld, component: %d\n", this->thisIndex, i, myVertices[i].vertexID, myVertices[i].parent, myVertices[i].componentNumber);
}*/
myVertices = appVertices;
}

/**
* @brief performs a union on two vertices given their vertexIDs
*
* assumes the vertexIDs encode the information about the location of the vertex
* (it's chare index in the union find lib proxy and the local array index
* of the vertex). performs the actual union operation and carries
* it's associated runtime cost (cost depends on implementation selected)
*/
#ifndef ANCHOR_ALGO
void UnionFindLib::
union_request(long int vid1, long int vid2) {
union_request(uint64_t vid1, uint64_t vid2) {
assert(vid1!=vid2);
if (vid2 < vid1) {
// found a back edge, flip and reprocess
union_request(vid2, vid1);
}
else {
//std::pair<int,int> vid1_loc = appPtr->getLocationFromID(vid1);
std::pair<int, int> vid1_loc = getLocationFromID(vid1);

//message the chare containing first vertex to find boss1
//pass the initilizer ID for initiating path compression

findBossData d;
d.arrIdx = vid1_loc.second;
d.partnerOrBossID = vid2;
d.senderID = -1; // TODO: Is this okay? Or use INT_MIN
d.senderID = -1;
d.isFBOne = 1;
this->thisProxy[vid1_loc.first].insertDataFindBoss(d);

Expand All @@ -97,7 +125,7 @@ union_request(long int vid1, long int vid2) {
}
#else
void UnionFindLib::
union_request(long int v, long int w) {
union_request(uint64_t v, uint64_t w) {
std::pair<int, int> w_loc = getLocationFromID(w);
// message w to anchor to v
anchorData d;
Expand All @@ -109,8 +137,9 @@ union_request(long int v, long int w) {

#ifndef ANCHOR_ALGO
void UnionFindLib::
find_boss1(int arrIdx, long int partnerID, long int senderID) {
find_boss1(int arrIdx, uint64_t partnerID, uint64_t senderID) {
unionFindVertex *src = &myVertices[arrIdx];
CkAssert(src->vertexID != src->parent);
src->findOrAnchorCount++;

if (src->parent == -1) {
Expand Down Expand Up @@ -202,8 +231,9 @@ find_boss1(int arrIdx, long int partnerID, long int senderID) {


void UnionFindLib::
find_boss2(int arrIdx, long int boss1ID, long int senderID) {
unionFindVertex *src = &myVertices[arrIdx];
find_boss2(int arrIdx, uint64_t boss1ID, uint64_t senderID) {
unionFindVertex *src = &myVertices[arrIdx]; // vid1, other field is vid2 (boss1ID) - same for find_boss1
CkAssert(src->vertexID != src->parent);
src->findOrAnchorCount++;

if (src->parent == -1) {
Expand Down Expand Up @@ -272,6 +302,7 @@ find_boss2(int arrIdx, long int boss1ID, long int senderID) {
// check if sender and current vertex are on different chares
if (senderID != -1 && !check_same_chares(senderID, curr->vertexID)) {
// short circuit the sender to point to grandparent

std::pair<int,int> sender_loc = getLocationFromID(senderID);
shortCircuitData scd;
scd.arrIdx = sender_loc.second;
Expand All @@ -285,7 +316,7 @@ find_boss2(int arrIdx, long int boss1ID, long int senderID) {
}
#else
void UnionFindLib::
anchor(int w_arrIdx, long int v, long int path_base_arrIdx) {
anchor(int w_arrIdx, uint64_t v, long int path_base_arrIdx) {
unionFindVertex *w = &myVertices[w_arrIdx];
w->findOrAnchorCount++;

Expand Down Expand Up @@ -365,7 +396,7 @@ anchor(int w_arrIdx, long int v, long int path_base_arrIdx) {

// perform local path compression
void UnionFindLib::
local_path_compression(unionFindVertex *src, long int compressedParent) {
local_path_compression(unionFindVertex *src, uint64_t compressedParent) {
unionFindVertex* tmp;
// An infinite loop if this function is called on itself (a node which does not have itself as its parent)
while (src->parent != compressedParent) {
Expand All @@ -378,7 +409,7 @@ local_path_compression(unionFindVertex *src, long int compressedParent) {

// check if two vertices are on same chare
bool UnionFindLib::
check_same_chares(long int v1, long int v2) {
check_same_chares(uint64_t v1, uint64_t v2) {
std::pair<int,int> v1_loc = getLocationFromID(v1);
std::pair<int,int> v2_loc = getLocationFromID(v2);
if (v1_loc.first == v2_loc.first)
Expand All @@ -392,11 +423,12 @@ short_circuit_parent(shortCircuitData scd) {
unionFindVertex *src = &myVertices[scd.arrIdx];
//CkPrintf("[TP %d] Short circuiting %ld from current parent %ld to grandparent %ld\n", thisIndex, src->vertexID, src->parent, grandparentID);
src->parent = scd.grandparentID;
CkAssert(src->parent != src->vertexID); // TODO: remove assert
}

// function to implement simple path compression; currently unused
void UnionFindLib::
compress_path(int arrIdx, long int compressedParent) {
compress_path(int arrIdx, uint64_t compressedParent) {
unionFindVertex *src = &myVertices[arrIdx];
//message the parent before reseting it
if (src->vertexID != compressedParent) {//reached the top of path
Expand All @@ -415,6 +447,13 @@ return_vertices() {

/** Functions for finding connected components **/

/**
* @brief After performing all union_request calls, labels connected components
* across all union find chares with coherent indexing starting with index 0 for
* component 0
*
* @param cb Callback to be invoked after this function has finished
*/
void UnionFindLib::
find_components(CkCallback cb) {
postComponentLabelingCb = cb;
Expand All @@ -433,8 +472,7 @@ find_components(CkCallback cb) {

// send local count to prefix library
CkCallback doneCb(CkReductionTarget(UnionFindLib, boss_count_prefix_done), thisProxy);
Prefix* myPrefixElem = prefixLibArray[thisIndex].ckLocal();
myPrefixElem->startPrefixCalculation(myLocalNumBosses, doneCb);
prefixLibArray[thisIndex].startPrefixCalculation(myLocalNumBosses, doneCb);
//CkPrintf("[%d] Local num bosses: %d\n", thisIndex, myLocalNumBosses);
}

Expand All @@ -446,7 +484,7 @@ boss_count_prefix_done(int totalCount) {
Prefix* myPrefixElem = prefixLibArray[thisIndex].ckLocal();
int v = myPrefixElem->getValue();
int myStartIndex = v - myLocalNumBosses;
//CkPrintf("[%d] My start index: %d\n", thisIndex, myStartIndex);
CkAssert(myStartIndex >= 0);

// start labeling my local bosses from myStartIndex
// ensures sequential numbering of components
Expand Down Expand Up @@ -487,7 +525,10 @@ start_component_labeling() {
// an internal node or leaf node, request parent for boss
std::pair<int, int> parent_loc = getLocationFromID(v->parent);
//this->thisProxy[parent_loc.first].need_boss(parent_loc.second, v->vertexID);
uint64_t data = ((uint64_t) parent_loc.second) << 32 | ((uint64_t) v->vertexID);
// uint64_t data = ((uint64_t) parent_loc.second) << 32 | ((uint64_t) v->vertexID);
needBossData data;
data.arrIdx = parent_loc.second;
data.senderID = v->vertexID;
this->thisProxy[parent_loc.first].insertDataNeedBoss(data);
}
}
Expand All @@ -512,9 +553,9 @@ insertDataFindBoss(const findBossData & data) {
}

void UnionFindLib::
insertDataNeedBoss(const uint64_t & data) {
int arrIdx = (int)(data >> 32);
long int fromID = (long int)(data & 0xffffffff);
insertDataNeedBoss(const needBossData & data) {
int arrIdx = data.arrIdx;
uint64_t fromID = data.senderID;
this->need_boss(arrIdx, fromID);
}

Expand All @@ -526,17 +567,18 @@ insertDataAnchor(const anchorData & data) {
#endif

void UnionFindLib::
need_boss(int arrIdx, long int fromID) {
// one of children of this node needs boss, handle by either replying immediately
// or queueing the request
need_boss(int arrIdx, uint64_t fromID) {
// one of children of this node needs boss, handle by either
// replying immediately or queueing the request

if (myVertices[arrIdx].componentNumber != -1) {
// component already set, reply back
std::pair<int, int> requestor_loc = getLocationFromID(fromID);
if (requestor_loc.first == thisIndex)
if (requestor_loc.first == thisIndex) {
set_component(requestor_loc.second, myVertices[arrIdx].componentNumber);
else
} else {
this->thisProxy[requestor_loc.first].set_component(requestor_loc.second, myVertices[arrIdx].componentNumber);
}
}
else {
// boss still not found, queue the request
Expand All @@ -549,19 +591,28 @@ set_component(int arrIdx, long int compNum) {
myVertices[arrIdx].componentNumber = compNum;

// since component number is set, respond to your requestors
std::vector<long int>::iterator req_iter = myVertices[arrIdx].need_boss_requests.begin();
while (req_iter != myVertices[arrIdx].need_boss_requests.end()) {
long int requestorID = *req_iter;
std::vector<uint64_t> need_boss_queue = myVertices[arrIdx].need_boss_requests;
while (!need_boss_queue.empty()) {
uint64_t requestorID = (need_boss_queue).back();
std::pair<int, int> requestor_loc = getLocationFromID(requestorID);
if (requestor_loc.first == thisIndex)
if (requestor_loc.first == thisIndex) {
set_component(requestor_loc.second, compNum);
else
} else {
this->thisProxy[requestor_loc.first].set_component(requestor_loc.second, compNum);
}
// done with current requestor, delete from request queue
req_iter = myVertices[arrIdx].need_boss_requests.erase(req_iter);
need_boss_queue.pop_back();
}
}

/**
* @brief discards components with number of vertices less than or equal to the
* threshold given and labels them with component number -1
*
* @param threshold the minimum number of vertices for a component must be
* strictly greater than this number
* @param appReturnCb Callback to be invoked upon completion
*/
void UnionFindLib::
prune_components(int threshold, CkCallback appReturnCb) {
componentPruneThreshold = threshold;
Expand Down Expand Up @@ -674,7 +725,19 @@ done_profiling(int total_count) {
}
}

// library initialization function
/**
* @brief initializes unionFindLib and returns a union find lib proxy
*
* Takes a chare array where vertices are stored and creates a union find chare
* array that is a shadow array of it. Intended so that when accessing vertices
* on the application level, one can easily make a invoke a local function
* on the corresponding union find chare using CkLocal()
*
* @param clientArray chare array that union find proxy will become shadow array
* of
* @param n number of chares in the clientArray
* @return CProxy_UnionFindLib the chare array union find proxy
*/
CProxy_UnionFindLib UnionFindLib::
unionFindInit(CkArrayID clientArray, int n) {
CkArrayOptions opts(n);
Expand Down
Loading