Skip to content
Snippets Groups Projects
test_FreeNonzeros.c 4.59 KiB
Newer Older
#include "FreeNonzeros.h"
#include "DistributeMat.h"
#include "DistributeVecLib.h"
#include <math.h>

void test_FreeNonzeros(int symmetric);

int main(int argc, char **argv) {

    printf("Test FreeNonzeros: ");
    
    SetRandomSeed(111);
    /*struct timeval tv;
    gettimeofday(&tv,NULL);
    unsigned long time_in_micros = 1000000 * tv.tv_sec + tv.tv_usec;
    SetRandomSeed(time_in_micros);*/
    
    test_FreeNonzeros(FALSE);
    test_FreeNonzeros(TRUE);
    
    printf("OK\n");
    exit(0);

} /* end main */

/**
 * Compute the total communication volume of a matrix.
 */
long ComputeVolume(struct sparsematrix *pM, int symmetric) {
    if(symmetric) {
        SparseMatrixSymmetric2Full(pM);
    }
    
    long tmp, ComVolV, ComVolU;
    CalcCom(pM, NULL, ROW, &ComVolV, &tmp, &tmp, &tmp, &tmp);
    CalcCom(pM, NULL, COL, &ComVolU, &tmp, &tmp, &tmp, &tmp);
    
    if(symmetric) {
        SparseMatrixFull2Symmetric(pM, 'S');
    }
    
    return ComVolV+ComVolU;

} /* end ComputeVolume */


/**
 * Test ImproveFreeNonzeros*()
 * 
 * Input:
 * symmetric: Whether the matrix should be symmetric
void test_FreeNonzeros(int symmetric) {
    
    struct sparsematrix A;
    struct sparsematrix *pA = &A;
    struct opts options;
    
    options.SymmetricMatrix_UseSingleEntry = symmetric ? SingleEntYes : SingleEntNo;
    
    long t, p, i, j;
    long P = 5, m = 20, n = 20;
    
    /* Set up matrix struct */
    MMSparseMatrixInit(pA);
    pA->m = m;
    pA->n = n;
    pA->NrNzElts = P*(m+n)+((m-P)*(n-P))/5;
    pA->NrProcs = P; /* maximum number of parts */

    pA->i = (long *)malloc(pA->NrNzElts*sizeof(long));
    pA->j = (long *)malloc(pA->NrNzElts*sizeof(long));
    pA->Pstart = (long *)malloc((P+1)*sizeof(long));
    
    if (pA->i == NULL || pA->j == NULL || pA->Pstart == NULL) {
        printf("Error\n");
        exit(1);
    }
    
    pA->MMTypeCode[0]='D'; /* normal matrix */
    pA->MMTypeCode[1]='C'; /* coordinate scheme */
    pA->MMTypeCode[2]='P'; /* pattern only */
    if(symmetric)
        pA->MMTypeCode[3]='S'; /* symmetric */
    else
        pA->MMTypeCode[3]='G'; /* general, no symmetry */
    
    /* Fill matrix */
    t = 0;
    for(p=0; p<P; ++p) {
        /* First, fill rows and columns such that we have many processors per row/column */
        pA->Pstart[p] = t;
        for(i=P; i<pA->m; ++i) {
            if(Random1(0, 2) == 0) {
                continue;
            }
            pA->i[t] = i;
            pA->j[t] = p;
            ++t;
        }
        if(!symmetric) {
            for(j=P; j<pA->n; ++j) {
                if(Random1(0, 2) == 0) {
                    continue;
                }
                pA->i[t] = p;
                pA->j[t] = j;
                ++t;
            }
        }
    }
    
    /* Add additional nonzeros to last partition */
    i = j = 0;
    while(TRUE) {
        j += Random1(5, 10);
        if(symmetric) {
            while(j > i) {
                j -= i;
                ++i;
            }
        }
        else {
            while(j >= pA->n-P) {
                j -= pA->n-P;
                ++i;
            }
        }
        if(i >= pA->m-P) {
            break;
        }
        pA->i[t] = P+i;
        pA->j[t] = P+j;
        ++t;
    }
    pA->Pstart[P] = pA->NrNzElts = t;
    
    /* We should provide a procs array */
    int *procs = (int *)malloc(P*sizeof(int));
    if (procs == NULL) {
        printf("Error\n");
        exit(1);
    }
    for(p=0; p<P; ++p) {
        procs[p] = 1;
    }
    
    /* Compute statistics before applying algorithm */
    long totalImbalanceBefore = 0, weight;
    long avgNrNzElts = pA->NrNzElts / P;
    for(p=0; p<P; ++p) {
        weight = ComputeWeight(pA, pA->Pstart[p], pA->Pstart[p+1]-1, NULL, &options);
        totalImbalanceBefore += abs(weight-avgNrNzElts);
    }
    long volumeBefore = ComputeVolume(pA, symmetric);
    
    /* Run algorithm */
    ImproveFreeNonzeros(pA, &options, procs, 3, 4);
    
    /* Compute statistics after applying algorithm */
    long totalImbalanceAfter = 0.0;
    for(p=0; p<P; ++p) {
        weight = ComputeWeight(pA, pA->Pstart[p], pA->Pstart[p+1]-1, NULL, &options);
        totalImbalanceAfter += abs(weight-avgNrNzElts);
    }
    long volumeAfter = ComputeVolume(pA, symmetric);
    
    /* Check that the total imbalance has not increased */
    if(totalImbalanceAfter > totalImbalanceBefore) {
        printf("Error1\n");
        exit(1);
    }
    
    /* Check that the volume has not increased */
    if(volumeAfter > volumeBefore) {
        printf("Error2\n");
        exit(1);
    }
    
    free(procs);
    MMDeleteSparseMatrix(pA);
    
} /* end test_FreeNonzeros */