bool MParted::MParted_Core::create(const MParted::Device & device, MParted::Partition & new_partition) {
    // Perfom alignment
    if (!snapToAlignment(device, new_partition))
        return false;

    if (new_partition.type == MParted::TYPE_EXTENDED) {
        return createPartition(new_partition);
    }
    else {
        MParted::Byte_Value fsMIN = 0;
        for (int t = 0 ; t < filesystems.size(); t++) {
            if (filesystems[t]->getFilesystemType() == new_partition.filesystem) {
                fsMIN = filesystems[t]->getFilesystemMIN();
                break;
            }
        }

        if (!createPartition(new_partition, (fsMIN / new_partition.sector_size)))
            return false;

        if (new_partition.filesystem == MParted::FS_UNFORMATTED)
            return true;
        else
            return (setPartitionType(new_partition) && createFilesystem(new_partition));
    }

    return false;
}
Example #2
0
bool fileSplitter::splitfile(){
    int i = 0;
    try
    {
        ifstream is(inputFile);
        if(!is){
            cout<<"fail open"<<endl;
        }
        is.seekg (0, is.end);
        size_t length = is.tellg();
        is.seekg (0, is.beg);
	cout << "file len:" << length << endl;        
        if(!prepareSplit(length)){
            cout << "fileSplitter::splitfile : buffer allocation returns error" << endl;
            return false;
        }
        for (i = 0; i < splitCount; i++){
            createPartition(is, i);
        }
        is.close();
        return true;
        
    }
    catch (exception& e)
    {
        cout << e.what() << endl;
        cout << "at" << i << "th partition" << endl ;
        
    }
    return false;
}
Example #3
0
/* =============================================================================
 * genScalData
 * =============================================================================
 */
void
genScalData (void* argPtr)
{
    TM_THREAD_ENTER();

    graphSDG* SDGdataPtr = (graphSDG*)argPtr;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    /*
     * STEP 0: Create the permutations required to randomize the vertices
     */

    random_t* stream = PRANDOM_ALLOC();
    assert(stream);
    PRANDOM_SEED(stream, myId);

    ULONGINT_T* permV; /* the vars associated with the graph tuple */

    if (myId == 0) {
        permV = (ULONGINT_T*)P_MALLOC(TOT_VERTICES * sizeof(ULONGINT_T));
        assert(permV);
        global_permV = permV;
    }

    thread_barrier_wait();

    permV = global_permV;

    long i;
    long i_start;
    long i_stop;
    createPartition(0, TOT_VERTICES, myId, numThread, &i_start, &i_stop);

    /* Initialize the array */
    for (i = i_start; i < i_stop; i++) {
        permV[i] = i;
    }

    thread_barrier_wait();

    for (i = i_start; i < i_stop; i++) {
        long t1 = PRANDOM_GENERATE(stream);
        long t = i + t1 % (TOT_VERTICES - i);
        if (t != i) {
            __transaction_atomic {
                long t2 = permV[t];
                permV[t] = permV[i];
                permV[i] = t2;
            }
        }
    }
void placement::partitionFormation() {
	moduleImpl* seed;
	hashlib::pool<moduleImpl*> moduleSet;

	for (namedModulePair& m : core->subModules)
		moduleSet.insert(m.second);

	while (!moduleSet.empty()) {
		seed = selectPartitionSeed(moduleSet);
		moduleSet.erase(seed);
		allPartitions.emplace_back(createPartition(moduleSet, seed));
	}
}
Example #5
0
/* =============================================================================
 * findSubGraphs0
 * =============================================================================
 */
void
findSubGraphs0 (void* argPtr)
{
    graph* GPtr                = ((findSubGraphs0_arg_t*)argPtr)->GPtr;
    V*     intWtVList          = ((findSubGraphs0_arg_t*)argPtr)->intWtVList;
    V*     strWtVList          = ((findSubGraphs0_arg_t*)argPtr)->strWtVList;
    edge*  maxIntWtList        = ((findSubGraphs0_arg_t*)argPtr)->maxIntWtList;
    long   maxIntWtListSize    = ((findSubGraphs0_arg_t*)argPtr)->maxIntWtListSize;
    edge*  soughtStrWtList     = ((findSubGraphs0_arg_t*)argPtr)->soughtStrWtList;
    long   soughtStrWtListSize = ((findSubGraphs0_arg_t*)argPtr)->soughtStrWtListSize;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    long i;
    long i_start;
    long i_stop;

    createPartition(0,
                    (maxIntWtListSize + soughtStrWtListSize),
                    myId,
                    numThread,
                    &i_start,
                    &i_stop);

    for (i = i_start; i < i_stop; i++) {
        if (i < maxIntWtListSize) {
            unsigned long j;
            for (j = 0; j < GPtr->numVertices; j++) {
                intWtVList[i*(GPtr->numVertices)+j].num = 0;
                intWtVList[i*(GPtr->numVertices)+j].depth = 0;
            }
        } else {
            long t = i - maxIntWtListSize;
            unsigned long j;
            for (j = 0; j < GPtr->numVertices; j++) {
                strWtVList[t*(GPtr->numVertices)+j].num = 0;
                strWtVList[t*(GPtr->numVertices)+j].depth = 0;
            }
        }
    }

    thread_barrier_wait();

    LONGINT_T* visited = (LONGINT_T*)P_MALLOC(GPtr->numVertices * sizeof(LONGINT_T));
    assert(visited);

    /*
     * Each thread runs a BFS from endvertex of maxIntWtList edgeList
     */


    for (i = i_start; i < i_stop; i++) {

        unsigned long k;
        for (k = 0; k < GPtr->numVertices; k++) {
            visited[k] = 0;
        }

        if (i < maxIntWtListSize) {

            intWtVList[i*(GPtr->numVertices)+0].num = maxIntWtList[i].startVertex;
            intWtVList[i*(GPtr->numVertices)+0].depth = -1;

            intWtVList[i*(GPtr->numVertices)+1].num = maxIntWtList[i].endVertex;
            intWtVList[i*(GPtr->numVertices)+1].depth = 1;

            visited[(intWtVList[i*(GPtr->numVertices)+0]).num] = 1;
            visited[(intWtVList[i*(GPtr->numVertices)+1]).num] = 1;

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                long intWtListIndex = i*(GPtr->numVertices)+currIndex;
                depth = intWtVList[intWtListIndex].depth + 1;
                long j;
                long j_start = GPtr->outVertexIndex[intWtVList[intWtListIndex].num];
                long j_stop = j_start + GPtr->outDegree[intWtVList[intWtListIndex].num];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 0) {
                        visited[GPtr->outVertexList[j]] = 1;
                        intWtVList[i*(GPtr->numVertices)+verticesVisited].num =
                            GPtr->outVertexList[j];
                        intWtVList[i*(GPtr->numVertices)+verticesVisited].depth =
                            depth;
                        verticesVisited++;
                    }
                }
                if ((currIndex < verticesVisited - 1) &&
                    (verticesVisited < (long)GPtr->numVertices))
                {
                    currIndex++;
                    depth = intWtVList[i*(GPtr->numVertices)+currIndex].depth;
                } else {
                    break;
                }
            }

        } else {

            long t = i - maxIntWtListSize;

            strWtVList[t*(GPtr->numVertices)+0].num =
                (soughtStrWtList[t]).startVertex;
            strWtVList[t*(GPtr->numVertices)+0].depth = -1;

            strWtVList[t*(GPtr->numVertices)+1].num =
                (soughtStrWtList[t]).endVertex;
            strWtVList[t*(GPtr->numVertices)+1].depth = 1;

            visited[(strWtVList[t*(GPtr->numVertices)+0]).num] = 1;
            visited[(strWtVList[t*(GPtr->numVertices)+1]).num] = 1;

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                long strWtVListIndex = t*(GPtr->numVertices)+currIndex;
                depth = strWtVList[strWtVListIndex].depth + 1;
                long j;
                long j_start = GPtr->outVertexIndex[strWtVList[strWtVListIndex].num];
                long j_stop = j_start + GPtr->outDegree[strWtVList[strWtVListIndex].num];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 0) {
                        visited[GPtr->outVertexList[j]] = 1;
                        strWtVList[t*(GPtr->numVertices)+verticesVisited].num =
                            GPtr->outVertexList[j];
                        strWtVList[t*(GPtr->numVertices)+verticesVisited].depth =
                            depth;
                        verticesVisited++;
                    }
                }
                if (currIndex < verticesVisited - 1) {
                    currIndex++;
                    depth = strWtVList[t*(GPtr->numVertices)+currIndex].depth;
                } else {
                    break;
                }
            }

        }

    }

    P_FREE(visited);
}
Example #6
0
/* =============================================================================
 * findSubGraphs2
 * =============================================================================
 */
void
findSubGraphs2 (void* argPtr)
{
    graph* GPtr                = ((findSubGraphs2_arg_t*)argPtr)->GPtr;
    Vd*    intWtVDList         = ((findSubGraphs2_arg_t*)argPtr)->intWtVDList;
    Vd*    strWtVDList         = ((findSubGraphs2_arg_t*)argPtr)->strWtVDList;
    edge*  maxIntWtList        = ((findSubGraphs2_arg_t*)argPtr)->maxIntWtList;
    long   maxIntWtListSize    = ((findSubGraphs2_arg_t*)argPtr)->maxIntWtListSize;
    edge*  soughtStrWtList     = ((findSubGraphs2_arg_t*)argPtr)->soughtStrWtList;
    long   soughtStrWtListSize = ((findSubGraphs2_arg_t*)argPtr)->soughtStrWtListSize;

    long myId = thread_getId();
    long numThread = thread_getNumThread();


    long numSubArray = 30;
    long arraySize = 5*MAX_CLUSTER_SIZE;

    long i;
    long i_start;
    long i_stop;
    createPartition(0,
                    (maxIntWtListSize + soughtStrWtListSize),
                    myId,
                    numThread,
                    &i_start,
                    &i_stop);

    for (i = i_start; i < i_stop; i++) {
        if (i < maxIntWtListSize) {
            /* Initialize the DS and create one sub-array */
            intWtVDList[i].numArrays = 1;
            intWtVDList[i].arraySize =
                (ULONGINT_T*)P_MALLOC(numSubArray * sizeof(ULONGINT_T));
            assert(intWtVDList[i].arraySize);
            intWtVDList[i].arraySize[0] = 0;
            intWtVDList[i].vList = (V**)P_MALLOC(numSubArray*sizeof(V *));
            assert(intWtVDList[i].vList);
            intWtVDList[i].vList[0] = (V*)P_MALLOC(arraySize*sizeof(V));
            assert(intWtVDList[i].vList[0]);
            long j;
            for (j = 0; j < arraySize; j++) {
                intWtVDList[i].vList[0][j].num = 0;
                intWtVDList[i].vList[0][j].depth = 0;
            }
        } else {
            long t = i - maxIntWtListSize;
            strWtVDList[t].numArrays = 1;
            strWtVDList[t].arraySize =
                (ULONGINT_T*)P_MALLOC(numSubArray * sizeof(ULONGINT_T));
            assert(strWtVDList[t].arraySize);
            strWtVDList[t].arraySize[0] = 0;
            strWtVDList[t].vList = (V**)P_MALLOC(numSubArray * sizeof(V*));
            assert(strWtVDList[t].vList);
            strWtVDList[t].vList[0] = (V*)P_MALLOC(arraySize * sizeof(V));
            assert(strWtVDList[t].vList[0]);
            long j;
            for (j = 0; j < arraySize; j++) {
                strWtVDList[t].vList[0][j].num = 0;
                strWtVDList[t].vList[0][j].depth = 0;
            }
        }
    }

    thread_barrier_wait();

    char* visited = (char*)P_MALLOC(GPtr->numVertices * sizeof(char));
    assert(visited);

    /*
     * Each thread runs a BFS from endvertex of maxIntWtList edgeList
     */

    for (i = i_start; i < i_stop; i++) {

        unsigned long k;
        for (k = 0; k < GPtr->numVertices; k++) {
            visited[k] = 'u';
        }

        if (i < maxIntWtListSize) {

            intWtVDList[i].vList[0][0].num = maxIntWtList[i].startVertex;
            intWtVDList[i].vList[0][0].depth = -1;

            intWtVDList[i].vList[0][1].num = maxIntWtList[i].endVertex;
            intWtVDList[i].vList[0][1].depth = 1;

            intWtVDList[i].arraySize[0] = 2;

            visited[intWtVDList[i].vList[0][0].num] = 'v';
            visited[intWtVDList[i].vList[0][1].num] = 'v';

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                long currVListX = currIndex / arraySize;
                long currVListY = currIndex % arraySize;
                V* currV = &intWtVDList[i].vList[currVListX][currVListY];
                long vNum = currV->num;
                depth = currV->depth + 1;
                long j;
                long j_start = GPtr->outVertexIndex[vNum];
                long j_stop = j_start + GPtr->outDegree[vNum];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 'u') {
                        visited[GPtr->outVertexList[j]] = 'v';
                        long vListX = verticesVisited/arraySize;
                        long vListY = verticesVisited % arraySize;
                        V* v = &intWtVDList[i].vList[vListX][vListY];
                        v->num = GPtr->outVertexList[j];
                        v->depth = depth;
                        intWtVDList[i].arraySize[vListX]++;
                        verticesVisited++;
                    }
                }

                /* Check if we need to create a new array */
                if (((float) verticesVisited / (float) arraySize) > 0.5) {
                    /* create a new sub-array */
                    if (intWtVDList[i].numArrays !=
                        (unsigned long)(verticesVisited/arraySize + 2))
                    {
                        intWtVDList[i].numArrays++;
                        intWtVDList[i].vList[intWtVDList[i].numArrays-1] =
                            (V*)P_MALLOC(arraySize * sizeof(V));
                        assert(intWtVDList[i].vList[intWtVDList[i].numArrays-1]);
                        intWtVDList[i].arraySize[intWtVDList[i].numArrays-1] = 0;
                    }
                }

                if ((currIndex < verticesVisited - 1) &&
                    (verticesVisited < (long)GPtr->numVertices))
                {
                    currIndex++;
                    long vListX = currIndex / arraySize;
                    long vListY = currIndex % arraySize;
                    depth = intWtVDList[i].vList[vListX][vListY].depth;
                } else {
                    break;
                }
            }

        } else {

            long t = i - maxIntWtListSize;

            strWtVDList[t].vList[0][0].num = soughtStrWtList[t].startVertex;
            strWtVDList[t].vList[0][0].depth = -1;

            strWtVDList[t].vList[0][1].num = soughtStrWtList[t].endVertex;
            strWtVDList[t].vList[0][1].depth = 1;

            strWtVDList[t].arraySize[0] = 2;

            visited[strWtVDList[t].vList[0][0].num] = 'v';
            visited[strWtVDList[t].vList[0][1].num] = 'v';

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                long currVListX = currIndex / arraySize;
                long currVListY = currIndex % arraySize;
                V* currV = &strWtVDList[t].vList[currVListX][currVListY];
                long vNum = currV->num;
                depth = currV->depth + 1;
                long j;
                long j_start = GPtr->outVertexIndex[vNum];
                long j_stop = j_start + GPtr->outDegree[vNum];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 'u') {
                        visited[GPtr->outVertexList[j]] = 'v';
                        long vListX = verticesVisited / arraySize;
                        long vListY = verticesVisited % arraySize;
                        V* v = &strWtVDList[t].vList[vListX][vListY];
                        v->num = GPtr->outVertexList[j];
                        v->depth = depth;
                        strWtVDList[t].arraySize[vListX]++;
                        verticesVisited++;
                    }
                }

                /* Check if we need to create a new array */
                if (((float)verticesVisited /(float) arraySize) > 0.5) {
                    /* create a new sub-array */
                    if (strWtVDList[t].numArrays !=
                        (unsigned long)(verticesVisited/arraySize + 2))
                    {
                        strWtVDList[t].numArrays++;
                        strWtVDList[t].vList[strWtVDList[t].numArrays-1] =
                            (V*)P_MALLOC(arraySize * sizeof(V));
                        assert(strWtVDList[t].vList[strWtVDList[t].numArrays-1]);
                        strWtVDList[t].arraySize[strWtVDList[t].numArrays-1] = 0;
                    }
                }

                if ((currIndex < verticesVisited - 1) &&
                    ((unsigned long)verticesVisited < GPtr->numVertices))
                {
                    currIndex++;
                    long currVListX = currIndex / arraySize;
                    long currVListY = currIndex % arraySize;
                    depth = strWtVDList[t].vList[currVListX][currVListY].depth;
                } else {
                    break;
                }
            }

        }

    } /* for i */

    P_FREE(visited);
}
Example #7
0
/* =============================================================================
 * findSubGraphs1
 * =============================================================================
 */
void
findSubGraphs1 (void* argPtr)
{
    graph* GPtr                = ((findSubGraphs1_arg_t*)argPtr)->GPtr;
    Vl**   intWtVLList         = ((findSubGraphs1_arg_t*)argPtr)->intWtVLList;
    Vl**   strWtVLList         = ((findSubGraphs1_arg_t*)argPtr)->strWtVLList;
    edge*  maxIntWtList        = ((findSubGraphs1_arg_t*)argPtr)->maxIntWtList;
    long   maxIntWtListSize    = ((findSubGraphs1_arg_t*)argPtr)->maxIntWtListSize;
    edge*  soughtStrWtList     = ((findSubGraphs1_arg_t*)argPtr)->soughtStrWtList;
    long   soughtStrWtListSize = ((findSubGraphs1_arg_t*)argPtr)->soughtStrWtListSize;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    char* visited = (char*)P_MALLOC(GPtr->numVertices * sizeof(char));
    assert(visited);

    long i;
    long i_start;
    long i_stop;
    createPartition(0,
                    (maxIntWtListSize + soughtStrWtListSize),
                    myId,
                    numThread,
                    &i_start,
                    &i_stop);

    for (i = i_start; i < i_stop; i++) {

        unsigned long k;
        for (k = 0; k < GPtr->numVertices; k++)  {
            visited[k] = 'u';
        }

        if (i < maxIntWtListSize) {

            intWtVLList[i] = (Vl*)P_MALLOC(sizeof(Vl));
            assert(intWtVLList[i]);
            (intWtVLList[i])->num = maxIntWtList[i].startVertex;
            (intWtVLList[i])->depth = 0;
            visited[(intWtVLList[i])->num] = 'v';

            (intWtVLList[i])->next = (Vl*)P_MALLOC(sizeof(Vl));
            P_FREE((intWtVLList[i])->next);
            ((intWtVLList[i])->next)->num = maxIntWtList[i].endVertex;
            ((intWtVLList[i])->next)->depth = 1;
            visited[((intWtVLList[i])->next)->num] = 'v';

            Vl* currV = (intWtVLList[i])->next;
            Vl* startV = (intWtVLList[i])->next;

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((startV->depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                depth = startV->depth + 1;
                long j;
                long j_start = GPtr->outVertexIndex[startV->num];
                long j_stop = j_start + GPtr->outDegree[startV->num];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 'u') {
                        visited[GPtr->outVertexList[j]] = 'v';
                        currV->next = (Vl*)P_MALLOC(sizeof(Vl));
                        assert(currV->next);
                        (currV->next)->num = GPtr->outVertexList[j];
                        (currV->next)->depth = depth;
                        verticesVisited++;
                        currV = currV->next;
                    }
                }

                if ((currIndex < verticesVisited - 1) &&
                    (verticesVisited < (long)GPtr->numVertices))
                {
                   currIndex++;
                   startV = startV->next;
                } else {
                  break;
                }
            }
            currV->next = NULL;

        } else {

            long t = i - maxIntWtListSize;
            strWtVLList[t] = (Vl*)P_MALLOC(sizeof(Vl));
            assert(strWtVLList[t]);
            (strWtVLList[t])->num = soughtStrWtList[t].startVertex;
            (strWtVLList[t])->depth = 0;
            visited[(strWtVLList[t])->num] = 'v';

            (strWtVLList[t])->next = (Vl*)P_MALLOC(sizeof(Vl));
            assert((strWtVLList[t])->next);
            ((strWtVLList[t])->next)->num = soughtStrWtList[t].endVertex;
            ((strWtVLList[t])->next)->depth = 1;
            visited[((strWtVLList[t])->next)->num] = 'v';

            Vl* currV = (strWtVLList[t])->next;
            Vl* startV = (strWtVLList[t])->next;

            long depth = 1;
            long verticesVisited = 2;
            long currIndex = 1;

            while ((startV->depth < SUBGR_EDGE_LENGTH) ||
                   (verticesVisited == (long)GPtr->numVertices))
            {
                depth = startV->depth + 1;

                long j;
                long j_start = GPtr->outVertexIndex[startV->num];
                long j_stop = j_start + GPtr->outDegree[startV->num];
                for (j = j_start; j < j_stop; j++) {
                    if (visited[GPtr->outVertexList[j]] == 'u') {
                        visited[GPtr->outVertexList[j]] = 'v';
                        currV->next = (Vl*)P_MALLOC(sizeof(Vl));
                        assert(currV->next);
                        (currV->next)->num = GPtr->outVertexList[j];
                        (currV->next)->depth = depth;
                        verticesVisited++;
                        currV = currV->next;
                    }
                }

                if ((currIndex < verticesVisited - 1) &&
                    (verticesVisited < (long)GPtr->numVertices))
                {
                    currIndex++;
                    startV = startV->next;
                } else {
                    break;
                }
            }

            currV->next = NULL;

        }

    } /* for i */

    P_FREE(visited);
}
Example #8
0
/* =============================================================================
 * genScalData
 * =============================================================================
 */
void
genScalData (void* argPtr)
{
    TM_THREAD_ENTER();

    graphSDG* SDGdataPtr = (graphSDG*)argPtr;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    /*
     * STEP 0: Create the permutations required to randomize the vertices
     */

    random_t* stream = PRANDOM_ALLOC();
    assert(stream);
    PRANDOM_SEED(stream, myId);

    ULONGINT_T* permV; /* the vars associated with the graph tuple */

    if (myId == 0) {
        permV = (ULONGINT_T*)P_MALLOC(TOT_VERTICES * sizeof(ULONGINT_T));
        assert(permV);
        global_permV = permV;
    }

    thread_barrier_wait();

    permV = global_permV;

    long i;
    long i_start;
    long i_stop;
    createPartition(0, TOT_VERTICES, myId, numThread, &i_start, &i_stop);

    /* Initialize the array */
    for (i = i_start; i < i_stop; i++) {
        permV[i] = i;
    }

    thread_barrier_wait();

    for (i = i_start; i < i_stop; i++) {
        long t1 = PRANDOM_GENERATE(stream);
        long t = i + t1 % (TOT_VERTICES - i);
        if (t != i) {
        	AL_LOCK(0);
            TM_BEGIN();
            long t2 = (long)TM_SHARED_READ(permV[t]);
            TM_SHARED_WRITE(permV[t], TM_SHARED_READ(permV[i]));
            TM_SHARED_WRITE(permV[i], t2);
            TM_END();
        }
    }

    /*
     * STEP 1: Create Cliques
     */

    long* cliqueSizes;

    long estTotCliques = ceil(1.5 * TOT_VERTICES / ((1+MAX_CLIQUE_SIZE)/2));

    /*
     * Allocate mem for Clique array
     * Estimate number of clique required and pad by 50%
     */
    if (myId == 0) {
        cliqueSizes = (long*)P_MALLOC(estTotCliques * sizeof(long));
        assert(cliqueSizes);
        global_cliqueSizes = cliqueSizes;
    }

    thread_barrier_wait();

    cliqueSizes = global_cliqueSizes;

    createPartition(0, estTotCliques, myId, numThread, &i_start, &i_stop);

    /* Generate random clique sizes. */
    for (i = i_start; i < i_stop; i++) {
        cliqueSizes[i] = 1 + (PRANDOM_GENERATE(stream) % MAX_CLIQUE_SIZE);
    }

    thread_barrier_wait();

    long totCliques = 0;

    /*
     * Allocate memory for cliqueList
     */

    ULONGINT_T* lastVsInCliques;
    ULONGINT_T* firstVsInCliques;

    if (myId == 0) {

        lastVsInCliques = (ULONGINT_T*)P_MALLOC(estTotCliques * sizeof(ULONGINT_T));
        assert(lastVsInCliques);
        global_lastVsInCliques = lastVsInCliques;
        firstVsInCliques = (ULONGINT_T*)P_MALLOC(estTotCliques * sizeof(ULONGINT_T));
        assert(firstVsInCliques);
        global_firstVsInCliques = firstVsInCliques;

        /*
         * Sum up vertices in each clique to determine the lastVsInCliques array
         */

        lastVsInCliques[0] = cliqueSizes[0] - 1;
        for (i = 1; i < estTotCliques; i++) {
            lastVsInCliques[i] = cliqueSizes[i] + lastVsInCliques[i-1];
            if (lastVsInCliques[i] >= TOT_VERTICES-1) {
                break;
            }
        }
        totCliques = i + 1;

        global_totCliques = totCliques;

        /*
         * Fix the size of the last clique
         */
        cliqueSizes[totCliques-1] =
            TOT_VERTICES - lastVsInCliques[totCliques-2] - 1;
        lastVsInCliques[totCliques-1] = TOT_VERTICES - 1;

        firstVsInCliques[0] = 0;

    }

    thread_barrier_wait();

    lastVsInCliques  = global_lastVsInCliques;
    firstVsInCliques = global_firstVsInCliques;
    totCliques = global_totCliques;

    /* Compute start Vertices in cliques. */
    createPartition(1, totCliques, myId, numThread, &i_start, &i_stop);
    for (i = i_start; i < i_stop; i++) {
        firstVsInCliques[i] = lastVsInCliques[i-1] + 1;
    }

#ifdef WRITE_RESULT_FILES
    thread_barrier_wait();

    /* Write the generated cliques to file for comparison with Kernel 4 */
    if (myId == 0) {
        FILE* outfp = fopen("cliques.txt", "w");
        fprintf(outfp, "No. of cliques - %lu\n", totCliques);
        for (i = 0; i < totCliques; i++) {
            fprintf(outfp, "Clq %lu - ", i);
            long j;
            for (j = firstVsInCliques[i]; j <= lastVsInCliques[i]; j++) {
                fprintf(outfp, "%lu ", permV[j]);
            }
            fprintf(outfp, "\n");
        }
        fclose(outfp);
    }

    thread_barrier_wait();
#endif

    /*
     * STEP 2: Create the edges within the cliques
     */

    /*
     * Estimate number of edges - using an empirical measure
     */
    long estTotEdges;
    if (SCALE >= 12) {
        estTotEdges = ceil(((MAX_CLIQUE_SIZE-1) * TOT_VERTICES));
    } else {
        estTotEdges = ceil(1.2 * (((MAX_CLIQUE_SIZE-1)*TOT_VERTICES)
                                  * ((1 + MAX_PARAL_EDGES)/2) + TOT_VERTICES*2));
    }

    /*
     * Initialize edge counter
     */
    long i_edgePtr = 0;
    float p = PROB_UNIDIRECTIONAL;

    /*
     * Partial edgeLists
     */

    ULONGINT_T* startV;
    ULONGINT_T* endV;

    if (numThread > 3) {
        long numByte = 1.5 * (estTotEdges/numThread) * sizeof(ULONGINT_T);
        startV = (ULONGINT_T*)P_MALLOC(numByte);
        endV = (ULONGINT_T*)P_MALLOC(numByte);
    } else  {
        long numByte = (estTotEdges/numThread) * sizeof(ULONGINT_T);
        startV = (ULONGINT_T*)P_MALLOC(numByte);
        endV = (ULONGINT_T*)P_MALLOC(numByte);
    }
    assert(startV);
    assert(endV);

    /*
     * Tmp array to keep track of the no. of parallel edges in each direction
     */
    ULONGINT_T** tmpEdgeCounter =
        (ULONGINT_T**)P_MALLOC(MAX_CLIQUE_SIZE * sizeof(ULONGINT_T *));
    assert(tmpEdgeCounter);
    for (i = 0; i < MAX_CLIQUE_SIZE; i++) {
        tmpEdgeCounter[i] =
            (ULONGINT_T*)P_MALLOC(MAX_CLIQUE_SIZE * sizeof(ULONGINT_T));
        assert(tmpEdgeCounter[i]);
    }

    /*
     * Create edges in parallel
     */
     long i_clique;
     createPartition(0, totCliques, myId, numThread, &i_start, &i_stop);

     for (i_clique = i_start; i_clique < i_stop; i_clique++) {

        /*
         * Get current clique parameters
         */

        long i_cliqueSize = cliqueSizes[i_clique];
        long i_firstVsInClique = firstVsInCliques[i_clique];

        /*
         * First create at least one edge between two vetices in a clique
         */

        for (i = 0; i < i_cliqueSize; i++) {

            long j;
            for (j = 0; j < i; j++) {

                float r = (float)(PRANDOM_GENERATE(stream) % 1000) / (float)1000;
                if (r >= p) {

                    startV[i_edgePtr] = i + i_firstVsInClique;
                    endV[i_edgePtr] = j + i_firstVsInClique;
                    i_edgePtr++;
                    tmpEdgeCounter[i][j] = 1;

                    startV[i_edgePtr] = j + i_firstVsInClique;
                    endV[i_edgePtr] = i + i_firstVsInClique;
                    i_edgePtr++;
                    tmpEdgeCounter[j][i] = 1;

                } else  if (r >= 0.5) {

                    startV[i_edgePtr] = i + i_firstVsInClique;
                    endV[i_edgePtr] = j + i_firstVsInClique;
                    i_edgePtr++;
                    tmpEdgeCounter[i][j] = 1;
                    tmpEdgeCounter[j][i] = 0;

                } else {

                    startV[i_edgePtr] = j + i_firstVsInClique;
                    endV[i_edgePtr] = i + i_firstVsInClique;
                    i_edgePtr++;
                    tmpEdgeCounter[j][i] = 1;
                    tmpEdgeCounter[i][j] = 0;

                }

            } /* for j */
        } /* for i */

        if (i_cliqueSize != 1) {
            long randNumEdges = (long)(PRANDOM_GENERATE(stream)
                                       % (2*i_cliqueSize*MAX_PARAL_EDGES));
            long i_paralEdge;
            for (i_paralEdge = 0; i_paralEdge < randNumEdges; i_paralEdge++) {
                i = (PRANDOM_GENERATE(stream) % i_cliqueSize);
                long j = (PRANDOM_GENERATE(stream) % i_cliqueSize);
                if ((i != j) && (tmpEdgeCounter[i][j] < MAX_PARAL_EDGES)) {
                    float r = (float)(PRANDOM_GENERATE(stream) % 1000) / (float)1000;
                    if (r >= p) {
                        /* Copy to edge structure. */
                        startV[i_edgePtr] = i + i_firstVsInClique;
                        endV[i_edgePtr] = j + i_firstVsInClique;
                        i_edgePtr++;
                        tmpEdgeCounter[i][j]++;
                    }
                }
            }
        }

    } /* for i_clique */

    for (i = 0; i < MAX_CLIQUE_SIZE; i++) {
        P_FREE(tmpEdgeCounter[i]);
    }

    P_FREE(tmpEdgeCounter);


    /*
     * Merge partial edge lists
     */

    ULONGINT_T* i_edgeStartCounter;
    ULONGINT_T* i_edgeEndCounter;

    if (myId == 0) {
        i_edgeStartCounter = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(i_edgeStartCounter);
        global_i_edgeStartCounter = i_edgeStartCounter;
        i_edgeEndCounter = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(i_edgeEndCounter);
        global_i_edgeEndCounter = i_edgeEndCounter;
    }

    thread_barrier_wait();

    i_edgeStartCounter = global_i_edgeStartCounter;
    i_edgeEndCounter   = global_i_edgeEndCounter;

    i_edgeEndCounter[myId] = i_edgePtr;
    i_edgeStartCounter[myId] = 0;

    thread_barrier_wait();

    if (myId == 0) {
        for (i = 1; i < numThread; i++) {
            i_edgeEndCounter[i] = i_edgeEndCounter[i-1] + i_edgeEndCounter[i];
            i_edgeStartCounter[i] = i_edgeEndCounter[i-1];
        }
    }

    AL_LOCK(0);
    TM_BEGIN();
    TM_SHARED_WRITE(global_edgeNum,
                    ((long)TM_SHARED_READ(global_edgeNum) + i_edgePtr));
    TM_END();

    thread_barrier_wait();

    long edgeNum = global_edgeNum;

    /*
     * Initialize edge list arrays
     */

    ULONGINT_T* startVertex;
    ULONGINT_T* endVertex;

    if (myId == 0) {
        if (SCALE < 10) {
            long numByte = 2 * edgeNum * sizeof(ULONGINT_T);
            startVertex = (ULONGINT_T*)P_MALLOC(numByte);
            endVertex = (ULONGINT_T*)P_MALLOC(numByte);
        } else {
            long numByte = (edgeNum + MAX_PARAL_EDGES * TOT_VERTICES)
                           * sizeof(ULONGINT_T);
            startVertex = (ULONGINT_T*)P_MALLOC(numByte);
            endVertex = (ULONGINT_T*)P_MALLOC(numByte);
        }
        assert(startVertex);
        assert(endVertex);
        global_startVertex = startVertex;
        global_endVertex = endVertex;
    }

    thread_barrier_wait();

    startVertex = global_startVertex;
    endVertex = global_endVertex;

    for (i = i_edgeStartCounter[myId]; i < i_edgeEndCounter[myId]; i++) {
        startVertex[i] = startV[i-i_edgeStartCounter[myId]];
        endVertex[i] = endV[i-i_edgeStartCounter[myId]];
    }

    ULONGINT_T numEdgesPlacedInCliques = edgeNum;

    thread_barrier_wait();

    /*
     * STEP 3: Connect the cliques
     */

    i_edgePtr = 0;
    p = PROB_INTERCL_EDGES;

    /*
     * Generating inter-clique edges as given in the specs
     */

    createPartition(0, TOT_VERTICES, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {

        ULONGINT_T tempVertex1 = i;
        long h = totCliques;
        long l = 0;
        long t = -1;
        while (h - l > 1) {
            long m = (h + l) / 2;
            if (tempVertex1 >= firstVsInCliques[m]) {
                l = m;
            } else {
                if ((tempVertex1 < firstVsInCliques[m]) && (m > 0)) {
                    if (tempVertex1 >= firstVsInCliques[m-1]) {
                        t = m - 1;
                        break;
                    } else {
                        h = m;
                    }
                }
            }
        }

        if (t == -1) {
            long m;
            for (m = (l + 1); m < h; m++) {
                if (tempVertex1<firstVsInCliques[m]) {
                    break;
                }
            }
            t = m-1;
        }

        long t1 = firstVsInCliques[t];

        ULONGINT_T d;
        for (d = 1, p = PROB_INTERCL_EDGES; d < TOT_VERTICES; d *= 2, p /= 2) {

            float r = (float)(PRANDOM_GENERATE(stream) % 1000) / (float)1000;

            if (r <= p) {

                ULONGINT_T tempVertex2 = (i+d) % TOT_VERTICES;

                h = totCliques;
                l = 0;
                t = -1;
                while (h - l > 1) {
                    long m = (h + l) / 2;
                    if (tempVertex2 >= firstVsInCliques[m]) {
                        l = m;
                    } else {
                        if ((tempVertex2 < firstVsInCliques[m]) && (m > 0)) {
                            if (firstVsInCliques[m-1] <= tempVertex2) {
                                t = m - 1;
                                break;
                            } else {
                                h = m;
                            }
                        }
                    }
                }

                if (t == -1) {
                    long m;
                    for (m = (l + 1); m < h; m++) {
                        if (tempVertex2 < firstVsInCliques[m]) {
                            break;
                        }
                    }
                    t = m - 1;
                }

                long t2 = firstVsInCliques[t];

                if (t1 != t2) {
                    long randNumEdges =
                        PRANDOM_GENERATE(stream) % MAX_PARAL_EDGES + 1;
                    long j;
                    for (j = 0; j < randNumEdges; j++) {
                        startV[i_edgePtr] = tempVertex1;
                        endV[i_edgePtr] = tempVertex2;
                        i_edgePtr++;
                    }
                }

            } /* r <= p */

            float r0 = (float)(PRANDOM_GENERATE(stream) % 1000) / (float)1000;

            if ((r0 <= p) && (i-d>=0)) {

                ULONGINT_T tempVertex2 = (i-d) % TOT_VERTICES;

                h = totCliques;
                l = 0;
                t = -1;
                while (h - l > 1) {
                    long m = (h + l) / 2;
                    if (tempVertex2 >= firstVsInCliques[m]) {
                        l = m;
                    } else {
                        if ((tempVertex2 < firstVsInCliques[m]) && (m > 0)) {
                            if (firstVsInCliques[m-1] <= tempVertex2) {
                                t = m - 1;
                                break;
                            } else {
                                h = m;
                            }
                        }
                    }
                }

                if (t == -1) {
                    long m;
                    for (m = (l + 1); m < h; m++) {
                        if (tempVertex2 < firstVsInCliques[m]) {
                            break;
                        }
                    }
                    t = m - 1;
                }

                long t2 = firstVsInCliques[t];

                if (t1 != t2) {
                    long randNumEdges =
                        PRANDOM_GENERATE(stream) % MAX_PARAL_EDGES + 1;
                    long j;
                    for (j = 0; j < randNumEdges; j++) {
                        startV[i_edgePtr] = tempVertex1;
                        endV[i_edgePtr] = tempVertex2;
                        i_edgePtr++;
                    }
                }

            } /* r0 <= p && (i-d) > 0 */

        } /* for d, p */

    } /* for i */


    i_edgeEndCounter[myId] = i_edgePtr;
    i_edgeStartCounter[myId] = 0;

    if (myId == 0) {
        global_edgeNum = 0;
    }

    thread_barrier_wait();

    if (myId == 0) {
        for (i = 1; i < numThread; i++) {
            i_edgeEndCounter[i] = i_edgeEndCounter[i-1] + i_edgeEndCounter[i];
            i_edgeStartCounter[i] = i_edgeEndCounter[i-1];
        }
    }

    AL_LOCK(0);
    TM_BEGIN();
    TM_SHARED_WRITE(global_edgeNum,
                    ((long)TM_SHARED_READ(global_edgeNum) + i_edgePtr));
    TM_END();


    thread_barrier_wait();

    edgeNum = global_edgeNum;
    ULONGINT_T numEdgesPlacedOutside = global_edgeNum;

    for (i = i_edgeStartCounter[myId]; i < i_edgeEndCounter[myId]; i++) {
        startVertex[i+numEdgesPlacedInCliques] = startV[i-i_edgeStartCounter[myId]];
        endVertex[i+numEdgesPlacedInCliques] = endV[i-i_edgeStartCounter[myId]];
    }

    thread_barrier_wait();

    ULONGINT_T  numEdgesPlaced = numEdgesPlacedInCliques + numEdgesPlacedOutside;

    if (myId == 0) {

        SDGdataPtr->numEdgesPlaced = numEdgesPlaced;

        printf("Finished generating edges\n");
        printf("No. of intra-clique edges - %lu\n", numEdgesPlacedInCliques);
        printf("No. of inter-clique edges - %lu\n", numEdgesPlacedOutside);
        printf("Total no. of edges        - %lu\n", numEdgesPlaced);

        P_FREE(i_edgeStartCounter);
        P_FREE(i_edgeEndCounter);

        P_FREE(cliqueSizes);
        P_FREE(firstVsInCliques);
        P_FREE(lastVsInCliques);
    }

    thread_barrier_wait();

    P_FREE(startV);
    P_FREE(endV);

    /*
     * STEP 4: Generate edge weights
     */

    if (myId == 0) {
        SDGdataPtr->intWeight =
            (LONGINT_T*)P_MALLOC(numEdgesPlaced * sizeof(LONGINT_T));
        assert(SDGdataPtr->intWeight);
    }

    thread_barrier_wait();

    p = PERC_INT_WEIGHTS;
    ULONGINT_T numStrWtEdges  = 0;

    createPartition(0, numEdgesPlaced, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        float r = (float)(PRANDOM_GENERATE(stream) % 1000) / (float)1000;
        if (r <= p) {
            SDGdataPtr->intWeight[i] =
                1 + (PRANDOM_GENERATE(stream) % (MAX_INT_WEIGHT-1));
        } else {
            SDGdataPtr->intWeight[i] = -1;
            numStrWtEdges++;
        }
    }

    thread_barrier_wait();

    if (myId == 0) {
        long t = 0;
        for (i = 0; i < numEdgesPlaced; i++) {
            if (SDGdataPtr->intWeight[i] < 0) {
                SDGdataPtr->intWeight[i] = -t;
                t++;
            }
        }
    }

    AL_LOCK(0);
    TM_BEGIN();
    TM_SHARED_WRITE(global_numStrWtEdges,
                    ((long)TM_SHARED_READ(global_numStrWtEdges) + numStrWtEdges));
    TM_END();

    thread_barrier_wait();

    numStrWtEdges = global_numStrWtEdges;

    if (myId == 0) {
        SDGdataPtr->strWeight =
            (char*)P_MALLOC(numStrWtEdges * MAX_STRLEN * sizeof(char));
        assert(SDGdataPtr->strWeight);
    }

    thread_barrier_wait();

    createPartition(0, numEdgesPlaced, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        if (SDGdataPtr->intWeight[i] <= 0) {
            long j;
            for (j = 0; j < MAX_STRLEN; j++) {
                SDGdataPtr->strWeight[(-SDGdataPtr->intWeight[i])*MAX_STRLEN+j] =
                    (char) (1 + PRANDOM_GENERATE(stream) % 127);
            }
        }
    }

    /*
     * Choose SOUGHT STRING randomly if not assigned
     */

    if (myId == 0) {

        if (strlen(SOUGHT_STRING) != MAX_STRLEN) {
            SOUGHT_STRING = (char*)P_MALLOC(MAX_STRLEN * sizeof(char));
            assert(SOUGHT_STRING);
        }

        long t = PRANDOM_GENERATE(stream) % numStrWtEdges;
        long j;
        for (j = 0; j < MAX_STRLEN; j++) {
            SOUGHT_STRING[j] =
                (char) ((long) SDGdataPtr->strWeight[t*MAX_STRLEN+j]);
        }

    }

    thread_barrier_wait();

    /*
     * STEP 5: Permute Vertices
     */

    for (i = i_start; i < i_stop; i++) {
        startVertex[i] = permV[(startVertex[i])];
        endVertex[i] = permV[(endVertex[i])];
    }

    thread_barrier_wait();

    /*
     * STEP 6: Sort Vertices
     */

    /*
     * Radix sort with StartVertex as primary key
     */

    if (myId == 0) {
        long numByte = numEdgesPlaced * sizeof(ULONGINT_T);
        SDGdataPtr->startVertex = (ULONGINT_T*)P_MALLOC(numByte);
        assert(SDGdataPtr->startVertex);
        SDGdataPtr->endVertex = (ULONGINT_T*)P_MALLOC(numByte);
        assert(SDGdataPtr->endVertex);
    }

    thread_barrier_wait();

    all_radixsort_node_aux_s3(numEdgesPlaced,
                              startVertex,
                              SDGdataPtr->startVertex,
                              endVertex,
                              SDGdataPtr->endVertex);

    thread_barrier_wait();

    if (myId == 0) {
        P_FREE(startVertex);
        P_FREE(endVertex);
    }

    thread_barrier_wait();

    if (SCALE < 12) {

        /*
         * Sort with endVertex as secondary key
         */

        if (myId == 0) {

            long i0 = 0;
            long i1 = 0;
            i = 0;

            while (i < numEdgesPlaced) {

                for (i = i0; i < numEdgesPlaced; i++) {
                    if (SDGdataPtr->startVertex[i] !=
                        SDGdataPtr->startVertex[i1])
                    {
                        i1 = i;
                        break;
                    }
                }

                long j;
                for (j = i0; j < i1; j++) {
                    long k;
                    for (k = j+1; k < i1; k++) {
                        if (SDGdataPtr->endVertex[k] <
                            SDGdataPtr->endVertex[j])
                        {
                            long t = SDGdataPtr->endVertex[j];
                            SDGdataPtr->endVertex[j] = SDGdataPtr->endVertex[k];
                            SDGdataPtr->endVertex[k] = t;
                        }
                    }
                }

                if (SDGdataPtr->startVertex[i0] != TOT_VERTICES-1) {
                    i0 = i1;
                } else {
                    long j;
                    for (j=i0; j<numEdgesPlaced; j++) {
                        long k;
                        for (k=j+1; k<numEdgesPlaced; k++) {
                            if (SDGdataPtr->endVertex[k] <
                                SDGdataPtr->endVertex[j])
                            {
                                long t = SDGdataPtr->endVertex[j];
                                SDGdataPtr->endVertex[j] = SDGdataPtr->endVertex[k];
                                SDGdataPtr->endVertex[k] = t;
                            }
                        }
                    }
                }

            } /* while i < numEdgesPlaced */

        }

    } else {

        ULONGINT_T* tempIndex;

        if (myId == 0) {

            tempIndex =
                (ULONGINT_T*)P_MALLOC((TOT_VERTICES + 1) * sizeof(ULONGINT_T));
            assert(tempIndex);
            global_tempIndex = tempIndex;

            /*
             * Update degree of each vertex
             */

            tempIndex[0] = 0;
            tempIndex[TOT_VERTICES] = numEdgesPlaced;
            long i0 = 0;

            for (i=0; i < TOT_VERTICES; i++) {
                tempIndex[i+1] = tempIndex[i];
                long j;
                for (j = i0; j < numEdgesPlaced; j++) {
                    if (SDGdataPtr->startVertex[j] !=
                        SDGdataPtr->startVertex[i0])
                    {
                        if (SDGdataPtr->startVertex[i0] == i) {
                            tempIndex[i+1] = j;
                            i0 = j;
                            break;
                        }
                    }
                }
            }
        }

        thread_barrier_wait();

        tempIndex = global_tempIndex;

        /*
         * Insertion sort for now, replace with something better later on
         */
#if 0
        createPartition(0, TOT_VERTICES, myId, numThread, &i_start, &i_stop);

        for (i = i_start; i < i_stop; i++) {
            long j;
            for (j = tempIndex[i]; j < tempIndex[i+1]; j++) {
                long k;
                for (k = (j + 1); k < tempIndex[i+1]; k++) {
                    if (SDGdataPtr->endVertex[k] <
                        SDGdataPtr->endVertex[j])
                    {
                        long t = SDGdataPtr->endVertex[j];
                        SDGdataPtr->endVertex[j] = SDGdataPtr->endVertex[k];
                        SDGdataPtr->endVertex[k] = t;
                    }
                }
            }
        }
#else
        if (myId == 0) {
            for (i = 0; i < TOT_VERTICES; i++) {
                long j;
                for (j = tempIndex[i]; j < tempIndex[i+1]; j++) {
                    long k;
                    for (k = (j + 1); k < tempIndex[i+1]; k++) {
                        if (SDGdataPtr->endVertex[k] <
                            SDGdataPtr->endVertex[j])
                        {
                            long t = SDGdataPtr->endVertex[j];
                            SDGdataPtr->endVertex[j] = SDGdataPtr->endVertex[k];
                            SDGdataPtr->endVertex[k] = t;
                        }
                    }
                }
            }
        }
#endif

        if (myId == 0) {
            P_FREE(tempIndex);
        }

    } /* SCALE >= 12 */

    PRANDOM_FREE(stream);
    if (myId == 0) {
        P_FREE(permV);
    }

    TM_THREAD_EXIT();
}
Example #9
0
/* =============================================================================
 * computeGraph
 * =============================================================================
 */
void
computeGraph (void* argPtr)
{
    TM_THREAD_ENTER();

    graph*    GPtr       = ((computeGraph_arg_t*)argPtr)->GPtr;
    graphSDG* SDGdataPtr = ((computeGraph_arg_t*)argPtr)->SDGdataPtr;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    ULONGINT_T j;
    ULONGINT_T maxNumVertices = 0;
    ULONGINT_T numEdgesPlaced = SDGdataPtr->numEdgesPlaced;

    /*
     * First determine the number of vertices by scanning the tuple
     * startVertex list
     */

    long i;
    long i_start;
    long i_stop;
    createPartition(0, numEdgesPlaced, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        if (SDGdataPtr->startVertex[i] > maxNumVertices) {
            maxNumVertices = SDGdataPtr->startVertex[i];
        }
    }

    TM_BEGIN();
    long tmp_maxNumVertices = (long)TM_SHARED_READ_L(global_maxNumVertices);
    long new_maxNumVertices = MAX(tmp_maxNumVertices, maxNumVertices) + 1;
    TM_SHARED_WRITE_L(global_maxNumVertices, new_maxNumVertices);
    TM_END();

    thread_barrier_wait();

    maxNumVertices = global_maxNumVertices;

    if (myId == 0) {

        GPtr->numVertices = maxNumVertices;
        GPtr->numEdges    = numEdgesPlaced;
        GPtr->intWeight   = SDGdataPtr->intWeight;
        GPtr->strWeight   = SDGdataPtr->strWeight;

        for (i = 0; i < numEdgesPlaced; i++) {
            if (GPtr->intWeight[numEdgesPlaced-i-1] < 0) {
                GPtr->numStrEdges = -(GPtr->intWeight[numEdgesPlaced-i-1]) + 1;
                GPtr->numIntEdges = numEdgesPlaced - GPtr->numStrEdges;
                break;
            }
        }

        GPtr->outDegree =
            (LONGINT_T*)P_MALLOC((GPtr->numVertices) * sizeof(LONGINT_T));
        assert(GPtr->outDegree);

        GPtr->outVertexIndex =
            (ULONGINT_T*)P_MALLOC((GPtr->numVertices) * sizeof(ULONGINT_T));
        assert(GPtr->outVertexIndex);
    }

    thread_barrier_wait();

    createPartition(0, GPtr->numVertices, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        GPtr->outDegree[i] = 0;
        GPtr->outVertexIndex[i] = 0;
    }

    ULONGINT_T outVertexListSize = 0;

    thread_barrier_wait();

    ULONGINT_T i0 = -1UL;

    for (i = i_start; i < i_stop; i++) {

        ULONGINT_T k = i;
        if ((outVertexListSize == 0) && (k != 0)) {
            while (i0 == -1UL) {
                for (j = 0; j < numEdgesPlaced; j++) {
                    if (k == SDGdataPtr->startVertex[j]) {
                        i0 = j;
                        break;
                    }

                }
                k--;
            }
        }

        if ((outVertexListSize == 0) && (k == 0)) {
            i0 = 0;
        }

        for (j = i0; j < numEdgesPlaced; j++) {
            if (i == GPtr->numVertices-1) {
                break;
            }
            if ((i != SDGdataPtr->startVertex[j])) {
                if ((j > 0) && (i == SDGdataPtr->startVertex[j-1])) {
                    if (j-i0 >= 1) {
                        outVertexListSize++;
                        GPtr->outDegree[i]++;
                        ULONGINT_T t;
                        for (t = i0+1; t < j; t++) {
                            if (SDGdataPtr->endVertex[t] !=
                                SDGdataPtr->endVertex[t-1])
                            {
                                outVertexListSize++;
                                GPtr->outDegree[i] = GPtr->outDegree[i]+1;
                            }
                        }
                    }
                }
                i0 = j;
                break;
            }
        }

        if (i == GPtr->numVertices-1) {
            if (numEdgesPlaced-i0 >= 0) {
                outVertexListSize++;
                GPtr->outDegree[i]++;
                ULONGINT_T t;
                for (t = i0+1; t < numEdgesPlaced; t++) {
                    if (SDGdataPtr->endVertex[t] != SDGdataPtr->endVertex[t-1]) {
                        outVertexListSize++;
                        GPtr->outDegree[i]++;
                    }
                }
            }
        }

    } /* for i */

    thread_barrier_wait();

    prefix_sums(GPtr->outVertexIndex, GPtr->outDegree, GPtr->numVertices);

    thread_barrier_wait();

    TM_BEGIN();
    TM_SHARED_WRITE_L(
        global_outVertexListSize,
        ((long)TM_SHARED_READ_L(global_outVertexListSize) + outVertexListSize)
    );
    TM_END();

    thread_barrier_wait();

    outVertexListSize = global_outVertexListSize;

    if (myId == 0) {
        GPtr->numDirectedEdges = outVertexListSize;
        GPtr->outVertexList =
            (ULONGINT_T*)P_MALLOC(outVertexListSize * sizeof(ULONGINT_T));
        assert(GPtr->outVertexList);
        GPtr->paralEdgeIndex =
            (ULONGINT_T*)P_MALLOC(outVertexListSize * sizeof(ULONGINT_T));
        assert(GPtr->paralEdgeIndex);
        GPtr->outVertexList[0] = SDGdataPtr->endVertex[0];
    }

    thread_barrier_wait();

    /*
     * Evaluate outVertexList
     */

    i0 = -1UL;

    for (i = i_start; i < i_stop; i++) {

        ULONGINT_T k = i;
        while ((i0 == -1UL) && (k != 0)) {
            for (j = 0; j < numEdgesPlaced; j++) {
                if (k == SDGdataPtr->startVertex[j]) {
                    i0 = j;
                    break;
                }
            }
            k--;
        }

        if ((i0 == -1) && (k == 0)) {
            i0 = 0;
        }

        for (j = i0; j < numEdgesPlaced; j++) {
            if (i == GPtr->numVertices-1) {
                break;
            }
            if (i != SDGdataPtr->startVertex[j]) {
                if ((j > 0) && (i == SDGdataPtr->startVertex[j-1])) {
                    if (j-i0 >= 1) {
                        long ii = GPtr->outVertexIndex[i];
                        ULONGINT_T r = 0;
                        GPtr->paralEdgeIndex[ii] = i0;
                        GPtr->outVertexList[ii] = SDGdataPtr->endVertex[i0];
                        r++;
                        ULONGINT_T t;
                        for (t = i0+1; t < j; t++) {
                            if (SDGdataPtr->endVertex[t] !=
                                SDGdataPtr->endVertex[t-1])
                            {
                                GPtr->paralEdgeIndex[ii+r] = t;
                                GPtr->outVertexList[ii+r] = SDGdataPtr->endVertex[t];
                                r++;
                            }
                        }

                    }
                }
                i0 = j;
                break;
            }
        } /* for j */

        if (i == GPtr->numVertices-1) {
            ULONGINT_T r = 0;
            if (numEdgesPlaced-i0 >= 0) {
                long ii = GPtr->outVertexIndex[i];
                GPtr->paralEdgeIndex[ii+r] = i0;
                GPtr->outVertexList[ii+r] = SDGdataPtr->endVertex[i0];
                r++;
                ULONGINT_T t;
                for (t = i0+1; t < numEdgesPlaced; t++) {
                    if (SDGdataPtr->endVertex[t] != SDGdataPtr->endVertex[t-1]) {
                        GPtr->paralEdgeIndex[ii+r] = t;
                        GPtr->outVertexList[ii+r] = SDGdataPtr->endVertex[t];
                        r++;
                    }
                }
            }
        }

    } /* for i */

    thread_barrier_wait();

    if (myId == 0) {
        P_FREE(SDGdataPtr->startVertex);
        P_FREE(SDGdataPtr->endVertex);
        GPtr->inDegree =
            (LONGINT_T*)P_MALLOC(GPtr->numVertices * sizeof(LONGINT_T));
        assert(GPtr->inDegree);
        GPtr->inVertexIndex =
            (ULONGINT_T*)P_MALLOC(GPtr->numVertices * sizeof(ULONGINT_T));
        assert(GPtr->inVertexIndex);
    }

    thread_barrier_wait();

    for (i = i_start; i < i_stop; i++) {
        GPtr->inDegree[i] = 0;
        GPtr->inVertexIndex[i] = 0;
    }

    /* A temp. array to store the inplied edges */
    ULONGINT_T* impliedEdgeList;
    if (myId == 0) {
        impliedEdgeList = (ULONGINT_T*)P_MALLOC(GPtr->numVertices
                                                * MAX_CLUSTER_SIZE
                                                * sizeof(ULONGINT_T));
        global_impliedEdgeList = impliedEdgeList;
    }

    thread_barrier_wait();

    impliedEdgeList = global_impliedEdgeList;

    createPartition(0,
                    (GPtr->numVertices * MAX_CLUSTER_SIZE),
                    myId,
                    numThread,
                    &i_start,
                    &i_stop);

    for (i = i_start; i < i_stop; i++) {
        impliedEdgeList[i] = 0;
    }

    /*
     * An auxiliary array to store implied edges, in case we overshoot
     * MAX_CLUSTER_SIZE
     */

    ULONGINT_T** auxArr;
    if (myId == 0) {
        auxArr = (ULONGINT_T**)P_MALLOC(GPtr->numVertices * sizeof(ULONGINT_T*));
        assert(auxArr);
        global_auxArr = auxArr;
    }

    thread_barrier_wait();

    auxArr = global_auxArr;

    createPartition(0, GPtr->numVertices, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        /* Inspect adjacency list of vertex i */
        for (j = GPtr->outVertexIndex[i];
             j < (GPtr->outVertexIndex[i] + GPtr->outDegree[i]);
             j++)
        {
            ULONGINT_T v = GPtr->outVertexList[j];
            ULONGINT_T k;
            for (k = GPtr->outVertexIndex[v];
                 k < (GPtr->outVertexIndex[v] + GPtr->outDegree[v]);
                 k++)
            {
                if (GPtr->outVertexList[k] == i) {
                    break;
                }
            }
            if (k == GPtr->outVertexIndex[v]+GPtr->outDegree[v]) {
                TM_BEGIN();
                /* Add i to the impliedEdgeList of v */
                long inDegree = (long)TM_SHARED_READ_L(GPtr->inDegree[v]);
                TM_SHARED_WRITE_L(GPtr->inDegree[v], (inDegree + 1));
                if (inDegree < MAX_CLUSTER_SIZE) {
                    TM_SHARED_WRITE_L(impliedEdgeList[v*MAX_CLUSTER_SIZE+inDegree],
                                    i);
                } else {
                    /* Use auxiliary array to store the implied edge */
                    /* Create an array if it's not present already */
                    ULONGINT_T* a = NULL;
                    if ((inDegree % MAX_CLUSTER_SIZE) == 0) {
                        a = (ULONGINT_T*)TM_MALLOC(MAX_CLUSTER_SIZE
                                                   * sizeof(ULONGINT_T));
                        assert(a);
                        TM_SHARED_WRITE_P(auxArr[v], a);
                    } else {
                        a = auxArr[v];
                    }
                    TM_SHARED_WRITE_L(a[inDegree % MAX_CLUSTER_SIZE], i);
                }
                TM_END();
            }
        }
    } /* for i */

    thread_barrier_wait();

    prefix_sums(GPtr->inVertexIndex, GPtr->inDegree, GPtr->numVertices);

    if (myId == 0) {
        GPtr->numUndirectedEdges = GPtr->inVertexIndex[GPtr->numVertices-1]
                                   + GPtr->inDegree[GPtr->numVertices-1];
        GPtr->inVertexList =
            (ULONGINT_T *)P_MALLOC(GPtr->numUndirectedEdges * sizeof(ULONGINT_T));
    }

    thread_barrier_wait();

    /*
     * Create the inVertex List
     */

    for (i = i_start; i < i_stop; i++) {
        for (j = GPtr->inVertexIndex[i];
             j < (GPtr->inVertexIndex[i] + GPtr->inDegree[i]);
             j++)
        {
            if ((j - GPtr->inVertexIndex[i]) < MAX_CLUSTER_SIZE) {
                GPtr->inVertexList[j] =
                    impliedEdgeList[i*MAX_CLUSTER_SIZE+j-GPtr->inVertexIndex[i]];
            } else {
                GPtr->inVertexList[j] =
                    auxArr[i][(j-GPtr->inVertexIndex[i]) % MAX_CLUSTER_SIZE];
            }
        }
    }

    thread_barrier_wait();

    if (myId == 0) {
        P_FREE(impliedEdgeList);
    }

    for (i = i_start; i < i_stop; i++) {
        if (GPtr->inDegree[i] > MAX_CLUSTER_SIZE) {
            P_FREE(auxArr[i]);
        }
    }

    thread_barrier_wait();

    if (myId == 0) {
        P_FREE(auxArr);
    }

    TM_THREAD_EXIT();
}
Example #10
0
/* =============================================================================
 * getStartLists
 * =============================================================================
 */
void
getStartLists (void* argPtr)
{
    TM_THREAD_ENTER();

    graph* GPtr                = ((getStartLists_arg_t*)argPtr)->GPtr;
    edge** maxIntWtListPtr     = ((getStartLists_arg_t*)argPtr)->maxIntWtListPtr;
    long*  maxIntWtListSize    = ((getStartLists_arg_t*)argPtr)->maxIntWtListSize;
    edge** soughtStrWtListPtr  = ((getStartLists_arg_t*)argPtr)->soughtStrWtListPtr;
    long*  soughtStrWtListSize = ((getStartLists_arg_t*)argPtr)->soughtStrWtListSize;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    /*
     * Find Max Wt on each thread
     */

    LONGINT_T maxWeight = 0;

    long i;
    long i_start;
    long i_stop;
    createPartition(0, GPtr->numEdges, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        if (GPtr->intWeight[i] > maxWeight) {
            maxWeight = GPtr->intWeight[i];
        }
    }

    AL_LOCK(0);
    TM_BEGIN(9);
    long tmp_maxWeight = (long)TM_SHARED_READ(global_maxWeight);
    if (maxWeight > tmp_maxWeight) {
        TM_SHARED_WRITE(global_maxWeight, maxWeight);
    }
    TM_END();

    thread_barrier_wait();

    maxWeight = global_maxWeight;

    /*
     * Create partial lists
     */

    /*
     * Allocate mem. for temp edge list for each thread
     */
    long numTmpEdge = (5+ceil(1.5*(GPtr->numIntEdges)/MAX_INT_WEIGHT));
    edge* tmpEdgeList = (edge*)P_MALLOC(numTmpEdge * sizeof(edge));

    long i_edgeCounter = 0;

    for (i = i_start; i < i_stop; i++) {

        if (GPtr->intWeight[i] == maxWeight) {

            /* Find the corresponding endVertex */
            long j;
            for (j = 0; j < GPtr->numDirectedEdges; j++) {
                if (GPtr->paralEdgeIndex[j] > i) {
                    break;
                }
            }
            tmpEdgeList[i_edgeCounter].endVertex = GPtr->outVertexList[j-1];
            tmpEdgeList[i_edgeCounter].edgeNum = j-1;

            long t;
            for (t = 0; t < GPtr->numVertices; t++) {
                if (GPtr->outVertexIndex[t] > j-1) {
                    break;
                }
            }
            tmpEdgeList[i_edgeCounter].startVertex = t-1;

            i_edgeCounter++;

        }
    }

    /*
     * Merge partial edge lists
     */

    long* i_edgeStartCounter;
    long* i_edgeEndCounter;

    if (myId == 0) {
        i_edgeStartCounter = (long*)P_MALLOC(numThread * sizeof(long));
        assert(i_edgeStartCounter);
        global_i_edgeStartCounter = i_edgeStartCounter;
        i_edgeEndCounter = (long*)P_MALLOC(numThread * sizeof(long));
        assert(i_edgeEndCounter);
        global_i_edgeEndCounter = i_edgeEndCounter;

        *maxIntWtListSize = 0;
    }

    thread_barrier_wait();

    i_edgeStartCounter = global_i_edgeStartCounter;
    i_edgeEndCounter = global_i_edgeEndCounter;

    i_edgeEndCounter[myId] = i_edgeCounter;
    i_edgeStartCounter[myId] = 0;

    thread_barrier_wait();

    if (myId == 0) {
        for (i = 1; i < numThread; i++) {
            i_edgeEndCounter[i] = i_edgeEndCounter[i-1] + i_edgeEndCounter[i];
            i_edgeStartCounter[i] = i_edgeEndCounter[i-1];
        }
    }

    *maxIntWtListSize += i_edgeCounter;

    thread_barrier_wait();

    edge* maxIntWtList;

    if (myId == 0) {
        P_FREE(*maxIntWtListPtr);
        maxIntWtList = (edge*)P_MALLOC((*maxIntWtListSize) * sizeof(edge));
        assert(maxIntWtList);
        global_maxIntWtList = maxIntWtList;
    }

    thread_barrier_wait();

    maxIntWtList = global_maxIntWtList;

    for (i = i_edgeStartCounter[myId]; i<i_edgeEndCounter[myId]; i++) {
      (maxIntWtList[i]).startVertex = tmpEdgeList[i-i_edgeStartCounter[myId]].startVertex;
      (maxIntWtList[i]).endVertex = tmpEdgeList[i-i_edgeStartCounter[myId]].endVertex;
      (maxIntWtList[i]).edgeNum = tmpEdgeList[i-i_edgeStartCounter[myId]].edgeNum;
    }

    if (myId == 0) {
        *maxIntWtListPtr = maxIntWtList;
    }

    i_edgeCounter = 0;

    createPartition(0, GPtr->numStrEdges, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {

        if (strncmp(GPtr->strWeight+i*MAX_STRLEN,
                    SOUGHT_STRING,
                    MAX_STRLEN) == 0)
        {
            /*
             * Find the corresponding endVertex
             */

            long t;
            for (t = 0; t < GPtr->numEdges; t++) {
                if (GPtr->intWeight[t] == -i) {
                    break;
                }
            }

            long j;
            for (j = 0; j < GPtr->numDirectedEdges; j++) {
            if (GPtr->paralEdgeIndex[j] > t) {
                    break;
                }
            }
            tmpEdgeList[i_edgeCounter].endVertex = GPtr->outVertexList[j-1];
            tmpEdgeList[i_edgeCounter].edgeNum = j-1;

            for (t = 0; t < GPtr->numVertices; t++) {
                if (GPtr->outVertexIndex[t] > j-1) {
                    break;
                }
            }
            tmpEdgeList[i_edgeCounter].startVertex = t-1;
            i_edgeCounter++;
        }

    }

    thread_barrier_wait();

    i_edgeEndCounter[myId] = i_edgeCounter;
    i_edgeStartCounter[myId] = 0;

    if (myId == 0) {
        *soughtStrWtListSize = 0;
    }

    thread_barrier_wait();

    if (myId == 0) {
        for (i = 1; i < numThread; i++) {
            i_edgeEndCounter[i] = i_edgeEndCounter[i-1] + i_edgeEndCounter[i];
            i_edgeStartCounter[i] = i_edgeEndCounter[i-1];
        }
    }

    *soughtStrWtListSize += i_edgeCounter;

    thread_barrier_wait();

    edge* soughtStrWtList;

    if (myId == 0) {
        P_FREE(*soughtStrWtListPtr);
        soughtStrWtList = (edge*)P_MALLOC((*soughtStrWtListSize) * sizeof(edge));
        assert(soughtStrWtList);
        global_soughtStrWtList = soughtStrWtList;
    }

    thread_barrier_wait();

    soughtStrWtList = global_soughtStrWtList;

    for (i = i_edgeStartCounter[myId]; i < i_edgeEndCounter[myId]; i++) {
        (soughtStrWtList[i]).startVertex =
            tmpEdgeList[i-i_edgeStartCounter[myId]].startVertex;
        (soughtStrWtList[i]).endVertex =
            tmpEdgeList[i-i_edgeStartCounter[myId]].endVertex;
        (soughtStrWtList[i]).edgeNum =
            tmpEdgeList[i-i_edgeStartCounter[myId]].edgeNum;
    }

    thread_barrier_wait();

    if (myId == 0) {
        *soughtStrWtListPtr = soughtStrWtList;
        P_FREE(i_edgeStartCounter);
        P_FREE(i_edgeEndCounter);
    }

    P_FREE(tmpEdgeList);

    TM_THREAD_EXIT();
}
Example #11
0
/* =============================================================================
 * cutClusters
 * =============================================================================
 */
void
cutClusters (void* argPtr)
{
    TM_THREAD_ENTER();

    graph* GPtr = (graph*)argPtr;

    long myId = thread_getId();
    long numThread = thread_getNumThread();

    /*
     * Sort the vertex list by their degree
     */

    ULONGINT_T* Index;
    ULONGINT_T* neighbourArray;
    ULONGINT_T* IndexSorted;
    ULONGINT_T* neighbourArraySorted;

    if (myId == 0) {
        long numByte = GPtr->numVertices * sizeof(ULONGINT_T);
        Index = (ULONGINT_T*)P_MALLOC(numByte);
        assert(Index);
        global_Index = Index;
        neighbourArray = (ULONGINT_T*)P_MALLOC(numByte);
        assert(neighbourArray);
        global_neighbourArray = neighbourArray;
        IndexSorted = (ULONGINT_T*)P_MALLOC(numByte);
        assert(IndexSorted);
        global_IndexSorted = IndexSorted;
        neighbourArraySorted = (ULONGINT_T*)P_MALLOC(numByte);
        assert(neighbourArraySorted);
        global_neighbourArraySorted = neighbourArraySorted;
    }

    thread_barrier_wait();

    Index = global_Index;
    neighbourArray = global_neighbourArray;
    IndexSorted = global_IndexSorted;
    neighbourArraySorted = global_neighbourArraySorted;

    long i;
    long i_start;
    long i_stop;
    createPartition(0, GPtr->numVertices, myId, numThread, &i_start, &i_stop);

    for (i = i_start; i < i_stop; i++) {
        neighbourArray[i] = GPtr->inDegree[i] + GPtr->outDegree[i];
        Index[i] = i;
    }

    thread_barrier_wait();


    all_radixsort_node_aux_s3(GPtr->numVertices,
                              neighbourArray,
                              neighbourArraySorted,
                              Index,
                              IndexSorted);

    thread_barrier_wait();

    /*
     * Global array to keep track of vertex status:
     * -1 if a vertex hasn't been assigned to a cluster yet
     * t if it belongs to a cluster; t = iteration*numThread + myId
     */
    long* vStatus;

    edge* pCutSet;
    ULONGINT_T* startV;
    ULONGINT_T* clusterSize;

    if (myId == 0) {

        P_FREE(Index);
        P_FREE(neighbourArray);

        vStatus = (long*)P_MALLOC(GPtr->numVertices * sizeof(long));
        assert(vStatus);
        global_vStatus = vStatus;

        /*
         * Allocate mem. for the cut set list
         * Maintain local arrays initially and merge them in the end
         */

        if (SCALE < 12) {
            pCutSet =(edge*)P_MALLOC((1*(GPtr->numDirectedEdges)/numThread)
                                     * sizeof(edge));
        } else {
            pCutSet = (edge*)P_MALLOC((0.2*(GPtr->numDirectedEdges)/numThread)
                                      * sizeof(edge));
        }
        assert(pCutSet);
        global_pCutSet = pCutSet;

        /*
         * Vertex to start from, on each thread
         */
        startV = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(startV);
        global_startV = startV;
        clusterSize = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(clusterSize);
        global_clusterSize = clusterSize;
    }

    thread_barrier_wait();

    vStatus     = global_vStatus;
    pCutSet     = global_pCutSet;
    startV      = global_startV;
    clusterSize = global_clusterSize;

    for (i = i_start; i < i_stop; i++) {
        vStatus[i] = -1;
    }

    thread_barrier_wait();

    ULONGINT_T verticesVisited = 0;

#ifdef WRITE_RESULT_FILES
    FILE* outfp1 = NULL;
    if (myId == 0) {
        outfp1 = fopen("clusters.txt", "w");
        fprintf(outfp1, "\nKernel 4 - Extracted Clusters\n");
    }
#endif

    long iter = 0;
    ULONGINT_T currIndex = 0;
    ULONGINT_T cutSetIndex = 0;

    while (verticesVisited < GPtr->numVertices) {

        /* Clear start vertex array */
        startV[myId] = -1;
        clusterSize[myId] = 0;

        if (currIndex == GPtr->numVertices) {
            currIndex = 0;
        }

        thread_barrier_wait();

        /*
         * Choose vertices to start from
         * Done sequentially right now, can be parallelized
         */
        if (myId == 0) {
            long t;
            for (t = 0; t < numThread; t++) {
                long r;
                for (r = currIndex; r < GPtr->numVertices; r++) {
                    if (vStatus[IndexSorted[GPtr->numVertices - r - 1]] == -1) {
                        startV[t] = IndexSorted[GPtr->numVertices - r - 1];
                        vStatus[startV[t]] = iter * numThread + t;
                        long j;
                        for (j = 0; j < GPtr->outDegree[startV[t]]; j++) {
                            long outVertexListIndex =
                                j+GPtr->outVertexIndex[startV[t]];
                            long vStatusIndex =
                                GPtr->outVertexList[outVertexListIndex];
                            if (vStatus[vStatusIndex] == -1) {
                                vStatus[vStatusIndex] = iter * numThread + t;
                                clusterSize[t]++;
                            }
                        }
                        for (j = 0; j < GPtr->inDegree[startV[t]]; j++) {
                            long inVertexIndex = j+GPtr->inVertexIndex[startV[t]];
                            long vStatusIndex = GPtr->inVertexList[inVertexIndex];
                            if (vStatus[vStatusIndex] == -1) {
                                vStatus[vStatusIndex] = iter * numThread + t;
                                clusterSize[t]++;
                            }
                        }
                        currIndex = r+1;
                        break;
                    }
                }
            }
        }

        thread_barrier_wait();

        /*
         * Determine clusters and cut sets in parallel
         */

        i = startV[myId];

        ULONGINT_T cliqueSize = 0;

        /* If the thread has some vertex to start from */
        if (i != -1)  {

            cliqueSize = 1;

            /* clusterSize[myId] gives the no. of 'unassigned' vertices adjacent to the current vertex */
            if ((clusterSize[myId] >= 0.6*(GPtr->inDegree[i]+GPtr->outDegree[i])) ||
                ((iter > (GPtr->numVertices)/(numThread*MAX_CLUSTER_SIZE)) &&
                 (clusterSize[myId] > 0)))
            {

                /*
                 * Most of the adjacent vertices are unassigned,
                 * should be able to extract a cluster easily
                 */

                /* Inspect adjacency list */
                long j;
                for (j = 0; j < GPtr->outDegree[i]; j++) {

                    ULONGINT_T clusterCounter = 0;
                    ULONGINT_T cutSetIndexPrev = cutSetIndex;
                    ULONGINT_T cutSetCounter = 0;

                    if (vStatus[GPtr->outVertexList[j+GPtr->outVertexIndex[i]]] ==
                        iter * numThread + myId)
                    {

                        long v = GPtr->outVertexList[j+GPtr->outVertexIndex[i]];

                        /*
                         * Inspect vertices adjacent to v and determine if it belongs
                         * to a cluster or not
                         */
                        long k;
                        for (k = 0; k < GPtr->outDegree[v]; k++) {
                            long outVertexListIndex = k+GPtr->outVertexIndex[v];
                            long vStatusIndex = GPtr->outVertexList[outVertexListIndex];
                            if (vStatus[vStatusIndex] == (iter * numThread + myId)) {
                                clusterCounter++;
                            } else {
                                cutSetCounter++;
                                if (vStatus[vStatusIndex] == -1) {
                                    /* Ensure that an edge is not added twice to the list */
                                    pCutSet[cutSetIndex].startVertex = v;
                                    pCutSet[cutSetIndex].endVertex = vStatusIndex;
                                    cutSetIndex++;
                                }
                            }
                        }

                        if ((cutSetCounter >= clusterCounter) ||
                            ((SCALE < 9) &&
                             (clusterCounter <= 2) &&
                             (GPtr->inDegree[v]+GPtr->outDegree[v] >
                              clusterCounter + cutSetCounter) &&
                             (clusterSize[myId] > clusterCounter + 2)) ||
                            ((SCALE > 9) &&
                             (clusterCounter < 0.5*clusterSize[myId])))
                        {

                            /* v doesn't belong to this clique, free it */
                            vStatus[v] = -1;

                            /* Also add this edge to cutset list, removing previously added edges */
                            cutSetIndex = cutSetIndexPrev;
                            pCutSet[cutSetIndex].startVertex = i;
                            pCutSet[cutSetIndex].endVertex = v;
                            cutSetIndex++;

                        } else {

                            cliqueSize++;
                             /* Add edges in inVertexList also to cut Set */
                            for (k = 0; k < GPtr->inDegree[v]; k++) {
                                long inVertexListIndex = k+GPtr->inVertexIndex[v];
                                long vStatusIndex = GPtr->inVertexList[inVertexListIndex];
                                if (vStatus[vStatusIndex] == -1) {
                                    pCutSet[cutSetIndex].startVertex = v;
                                    pCutSet[cutSetIndex].endVertex = vStatusIndex;
                                    cutSetIndex++;
                                }
                            }

                        }

                    }

                }

                /* Do the same for the implied edges too */
                for (j = 0; j < GPtr->inDegree[i]; j++) {

                    ULONGINT_T clusterCounter = 0;
                    ULONGINT_T cutSetIndexPrev = cutSetIndex;
                    ULONGINT_T cutSetCounter = 0;

                    if (vStatus[GPtr->inVertexList[j+GPtr->inVertexIndex[i]]] ==
                        iter*numThread+myId)
                    {
                        long v = GPtr->inVertexList[j+GPtr->inVertexIndex[i]];

                        /* Inspect vertices adjacent to v and determine if it belongs to a cluster or not */
                        long k;
                        for (k = 0; k < GPtr->outDegree[v]; k++) {
                            long outVertexListIndex = k+GPtr->outVertexIndex[v];
                            long vStatusIndex = GPtr->outVertexList[outVertexListIndex];
                            if (vStatus[vStatusIndex] == iter*numThread+myId) {
                                clusterCounter++;
                            } else {
                                cutSetCounter++;
                                if (vStatus[vStatusIndex] == -1) {
                                    /* To ensure that an edge is not added twice to the list */
                                    pCutSet[cutSetIndex].startVertex = v;
                                    pCutSet[cutSetIndex].endVertex = vStatusIndex;
                                    cutSetIndex++;
                                }
                            }
                        }

                        if ((cutSetCounter >= clusterCounter) ||
                            ((SCALE < 9) &&
                             (clusterCounter <= 2) &&
                             (GPtr->inDegree[v]+GPtr->outDegree[v] >
                              clusterCounter + cutSetCounter)  &&
                             (clusterSize[myId] > clusterCounter + 2)) ||
                            ((SCALE > 9) &&
                             (clusterCounter < 0.5*clusterSize[myId])))
                        {
                            /* v doesn't belong to this clique, free it */
                            vStatus[v] = -1;
                            cutSetIndex = cutSetIndexPrev;
                            pCutSet[cutSetIndex].startVertex = i;
                            pCutSet[cutSetIndex].endVertex = v;
                            cutSetIndex++;

                        } else {

                            cliqueSize++;
                            /* Add edges in inVertexList also to cut Set */
                            for (k = 0; k < GPtr->inDegree[v]; k++) {
                                long inVertexListIndex = k+GPtr->inVertexIndex[v];
                                long vStatusIndex = GPtr->inVertexList[inVertexListIndex];
                                if (vStatus[vStatusIndex] == -1) {
                                    pCutSet[cutSetIndex].startVertex = v;
                                    pCutSet[cutSetIndex].endVertex = vStatusIndex;
                                    cutSetIndex++;
                                }
                            }

                        }

                    }

                }

            } /* i != -1 */

            if (clusterSize[myId] == 0)  {

              /* Only one vertex in cluster */
              cliqueSize = 1;

            } else {

                if ((clusterSize[myId] < 0.6*(GPtr->inDegree[i]+GPtr->outDegree[i])) &&
                    (iter <= GPtr->numVertices/(numThread*MAX_CLUSTER_SIZE)))
                {
                    /* High perc. of intra-clique edges, do not commit clique */
                    cliqueSize = 0;
                    vStatus[i] = -1;

                    long j;
                    for (j=0; j<GPtr->outDegree[i]; j++) {
                        long outVertexListIndex = j+GPtr->outVertexIndex[i];
                        long vStatusIndex = GPtr->outVertexList[outVertexListIndex];
                        if (vStatus[vStatusIndex] == iter*numThread+myId) {
                            vStatus[vStatusIndex] = -1;
                        }
                    }

                    for (j=0; j<GPtr->inDegree[i]; j++) {
                        long inVertexListIndex = j+GPtr->inVertexIndex[i];
                        long vStatusIndex = GPtr->inVertexList[inVertexListIndex];
                        if (vStatus[vStatusIndex] == iter*numThread+myId) {
                            vStatus[vStatusIndex] = -1;
                        }
                    }
                }

            }
        } /* if i != -1 */

        if (myId == 0) {
            global_cliqueSize = 0;
        }

        thread_barrier_wait();

#ifdef WRITE_RESULT_FILES
        /* Print to results.clq file */

        if (myId == 0) {
            long t;
            for (t = 0; t < numThread; t++) {
                if (startV[t] != -1) {
                    if (vStatus[startV[t]] == iter*numThread+t) {
                        fprintf(outfp1, "%lu ", startV[t]);
                        long j;
                        for (j = 0; j < GPtr->outDegree[startV[t]]; j++) {
                            long outVertexListIndex = j+GPtr->outVertexIndex[startV[t]];
                            long vStatusIndex = GPtr->outVertexList[outVertexListIndex];
                            if (vStatus[vStatusIndex] == iter*numThread+t) {
                                fprintf(outfp1, "%lu ", vStatusIndex);
                            }
                        }
                        for (j = 0; j < GPtr->inDegree[startV[t]]; j++) {
                            long inVertexListIndex = j+GPtr->inVertexIndex[startV[t]];
                            long vStatusIndex = GPtr->inVertexList[inVertexListIndex];
                            if (vStatus[vStatusIndex] == iter*numThread+t) {
                                fprintf(outfp1, "%lu ", vStatusIndex);
                            }
                        }
                        fprintf(outfp1, "\n");
                    }
                }
            }
        }

        thread_barrier_wait();
#endif /* WRITE_RESULTS_FILE */

        if (myId == 0) {
            iter++;
            global_iter = iter;
        }

        TM_BEGIN();
        long tmp_cliqueSize = (long)TM_SHARED_READ(global_cliqueSize);
        TM_SHARED_WRITE(global_cliqueSize, (tmp_cliqueSize + cliqueSize));
        TM_END();

        thread_barrier_wait();

        iter = global_iter;
        verticesVisited += global_cliqueSize;

        if ((verticesVisited >= 0.95*GPtr->numVertices) ||
            (iter > GPtr->numVertices/2))
        {
            break;
        }

    } /* while (verticesVisited < GPtr->numVertices) */

    thread_barrier_wait();

#ifdef WRITE_RESULT_FILES
    /* Take care of unmarked vertices */
    if (myId == 0) {
        if (verticesVisited < GPtr->numVertices) {
            for(i = 0; i < GPtr->numVertices; i++) {
                if (vStatus[i] == -1) {
                    vStatus[i] = iter*numThread+myId;
                    fprintf(outfp1, "%lu\n", i);
                    iter++;
                }
            }
        }
    }

    thread_barrier_wait();
#endif

    /*
     * Merge partial Cutset Lists
     */

    /* Temp vars for merging edge lists */
    ULONGINT_T* edgeStartCounter;
    ULONGINT_T* edgeEndCounter;

    if (myId == 0) {
        edgeStartCounter = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(edgeStartCounter);
        global_edgeStartCounter = edgeStartCounter;
        edgeEndCounter = (ULONGINT_T*)P_MALLOC(numThread * sizeof(ULONGINT_T));
        assert(edgeEndCounter);
        global_edgeEndCounter = edgeEndCounter;
    }

    thread_barrier_wait();

    edgeStartCounter = global_edgeStartCounter;
    edgeEndCounter   = global_edgeEndCounter;

    edgeEndCounter[myId] = cutSetIndex;
    edgeStartCounter[myId] = 0;

    thread_barrier_wait();

    if (myId == 0) {
        long t;
        for (t = 1; t < numThread; t++) {
            edgeEndCounter[t] = edgeEndCounter[t-1] + edgeEndCounter[t];
            edgeStartCounter[t] = edgeEndCounter[t-1];
        }
    }

    TM_BEGIN();
    long tmp_cutSetIndex = (long)TM_SHARED_READ(global_cutSetIndex);
    TM_SHARED_WRITE(global_cutSetIndex, (tmp_cutSetIndex + cutSetIndex));
    TM_END();

    thread_barrier_wait();

    cutSetIndex = global_cutSetIndex;
    ULONGINT_T cutSetCounter = cutSetIndex;

    /* Data struct. for storing edgeCut */
    edge* cutSet;

    if (myId == 0) {
        cutSet = (edge*)P_MALLOC(cutSetCounter * sizeof(edge));
        assert(cutSet);
        global_cutSet = cutSet;
    }

    thread_barrier_wait();

    cutSet = global_cutSet;

    long j;
    for (j = edgeStartCounter[myId]; j < edgeEndCounter[myId]; j++) {
        cutSet[j].startVertex = pCutSet[j-edgeStartCounter[myId]].startVertex;
        cutSet[j].endVertex = pCutSet[j-edgeStartCounter[myId]].endVertex;
    }

    thread_barrier_wait();

#ifdef WRITE_RESULT_FILES
    FILE* outfp2 = NULL;
    if (myId == 0) {
        outfp2 = fopen("edgeCut.txt", "w");
        fprintf(outfp2, "\nEdges in Cut Set - \n");
        for (i = 0; i < cutSetCounter; i++) {
            fprintf(outfp2, "[%lu %lu] ",
                    cutSet[i].startVertex, cutSet[i].endVertex);
        }
        fclose(outfp2);
        fclose(outfp1);
    }
#endif

    if (myId == 0) {
        P_FREE(edgeStartCounter);
        P_FREE(edgeEndCounter);
        P_FREE(pCutSet);
        P_FREE(IndexSorted);
        P_FREE(neighbourArraySorted);
        P_FREE(startV);
        P_FREE(clusterSize);
        P_FREE(cutSet);
        P_FREE(vStatus);
    }

    TM_THREAD_EXIT();
}