Example #1
0
GrB_Info random_matrix      // create a random double-precision matrix
(
    GrB_Matrix *A_output,   // handle of matrix to create
    bool make_symmetric,    // if true, return A as symmetric
    bool no_self_edges,     // if true, then do not create self edges
    int64_t nrows,          // number of rows
    int64_t ncols,          // number of columns
    int64_t nedges,         // number of edges
    int method,             // method to use: 0:setElement, 1:build,
    bool A_complex          // if true, create a Complex matrix
)
{
    GrB_Matrix Areal = NULL, Aimag = NULL, A = NULL ;
    *A_output = NULL ;
    GrB_Index *I = NULL, *J = NULL ;
    double *X = NULL ;
    GrB_Info info ;

    if (make_symmetric)
    {
        nrows = MAX (nrows, ncols) ;
        ncols = MAX (nrows, ncols) ;
    }

    //--------------------------------------------------------------------------
    // create a Complex matrix
    //--------------------------------------------------------------------------

    if (A_complex)
    {
        // Areal = real random matrix
        OK (random_matrix (&Areal, make_symmetric, no_self_edges, nrows,
            ncols, nedges, method, false)) ;
        // Aimag = real random matrix
        OK (random_matrix (&Aimag, make_symmetric, no_self_edges, nrows,
            ncols, nedges, method, false)) ;
        // A = Areal + imag(Aimag)
        OK (GrB_Matrix_new (&A, Complex, nrows, ncols)) ;
        OK (GrB_apply (A, NULL, NULL,         Complex_complex_real, Areal,
            NULL)) ;
        OK (GrB_apply (A, NULL, Complex_plus, Complex_complex_imag, Aimag,
            NULL)) ;
        *A_output = A ;
        A = NULL ;
        FREE_ALL ;
        return (GrB_SUCCESS) ;
    }

    //--------------------------------------------------------------------------
    // create a real double matrix (GrB_FP64)
    //--------------------------------------------------------------------------

    OK (GrB_Matrix_new (&A, GrB_FP64, nrows, ncols)) ;

    if (method == 0)
    {

        //----------------------------------------------------------------------
        // use GrB_Matrix_setElement: no need to allocate tuples
        //----------------------------------------------------------------------

        // This is just about as fast as the GrB_Matrix_build method with
        // non-blocking mode (about 10% more time, regardless of the problem
        // size).  This is mainly because setElement doesn't know how many
        // tuples will eventually be added, so it must dynamically reallocate
        // its internal storage.  In constrast, the arrays I, J, and X are a
        // fixed, known size and are not reallocated as tuples are added.

        // Note how simple this code is, below.  A user application can use
        // setElement without having to create its own I,J,X tuple lists.  It
        // can create the tuples in any order.  The code is simpler, and the
        // performance penalty is neglible.

        // With blocking mode, setElement is EXTREMELY slow, since the matrix
        // is rebuilt on every iteration.  In this case, it is easily a 1,000
        // or even a million times slower than using build when the matrix is
        // very large.  Don't attempt to do this with large matrices with
        // blocking mode enabled.  Actual run time could increase from 1 minute
        // to 1 year (!) in the extreme case, with a matrix that can be
        // generated on a commodity laptop.

        for (int64_t k = 0 ; k < nedges ; k++)
        {
            GrB_Index i = simple_rand_i ( ) % nrows ;
            GrB_Index j = simple_rand_i ( ) % ncols ;
            if (no_self_edges && (i == j)) continue ;
            double x = simple_rand_x ( ) ;
            // A (i,j) = x
            OK (GrB_Matrix_setElement (A, x, i, j)) ;
            if (make_symmetric)
            {
                // A (j,i) = x
                OK (GrB_Matrix_setElement (A, x, j, i)) ;
            }
        }
    }
    else
    {

        //----------------------------------------------------------------------
        // use GrB_Matrix_build: allocate initial space for tuples
        //----------------------------------------------------------------------

        // This method is harder for a user application to use.  It is slightly
        // faster than the setElement method.  Its performance is not affected
        // by the mode (blocking or non-blocking).

        int64_t s = ((make_symmetric) ? 2 : 1) * nedges + 1 ;
        I = malloc (s * sizeof (GrB_Index)) ;
        J = malloc (s * sizeof (GrB_Index)) ;
        X = malloc (s * sizeof (double   )) ;
        if (I == NULL || J == NULL || X == NULL)
        {   // out of memory
            FREE_ALL ;
            return (GrB_OUT_OF_MEMORY) ;
        }

        //----------------------------------------------------------------------
        // create the tuples
        //----------------------------------------------------------------------

        int64_t ntuples = 0 ;
        for (int64_t k = 0 ; k < nedges ; k++)
        {
            GrB_Index i = simple_rand_i ( ) % nrows ;
            GrB_Index j = simple_rand_i ( ) % ncols ;
            if (no_self_edges && (i == j)) continue ;
            double x = simple_rand_x ( ) ;
            // A (i,j) = x
            I [ntuples] = i ;
            J [ntuples] = j ;
            X [ntuples] = x ;
            ntuples++ ;
            if (make_symmetric)
            {
                // A (j,i) = x
                I [ntuples] = j ;
                J [ntuples] = i ;
                X [ntuples] = x ;
                ntuples++ ;
            }
        }

        //----------------------------------------------------------------------
        // build the matrix
        //----------------------------------------------------------------------

        OK (GrB_Matrix_build (A, I, J, X, ntuples, GrB_SECOND_FP64)) ;
        free (I) ;
        free (J) ;
        free (X) ;
    }

    *A_output = A ;
    return (GrB_SUCCESS) ;
}
Example #2
0
int main (void)
{
    double *x ;
    double tic [2], t ;
    int i ;

    fprintf (stderr, "simple_demo:\n") ;
    double n = ((double) LEN) / 1e6 ;

    /* calloc the space for more accurate timing */
    x = calloc (LEN, sizeof (double)) ;
    if (x == NULL)
    {
        fprintf (stderr, "simple_demo: out of memory\n") ;
        exit (1) ;
    }

    /* do lots of tics */
    simple_tic (tic) ;
    for (i = 0 ; i < LEN/10 ; i++)
    {
        double tic2 [2] ;
        simple_tic (tic2) ;
    }
    t = simple_toc (tic) ;
    printf ("time to call simple_tic %g million times: %g\n", n/10, t) ;

    /* generate random numbers */
    simple_tic (tic) ;
    for (i = 0 ; i < LEN ; i++)
    {
        x [i] = simple_rand_x ( ) ;
    }
    t = simple_toc (tic) ;

    /* report the result */
    printf ("time to generate %g million random numbers: %g\n", n, t) ;
    fprintf (stderr, "time to generate %g million random numbers: %g\n\n",
        n, t) ;

    /* these should be the same on any system and any compiler */
    printf ("first 10 random numbers:\n") ;
    for (i = 0 ; i < 10 ; i++)
    {
        printf ("%12.6f\n", x [i]) ;
    }

    /* generate random uint64_t numbers */
    double t1 ;

    simple_tic (tic) ;
    for (i = 0 ; i < LEN ; i++)
    {
        simple_rand_i ( ) ;
    }
    t1 = simple_toc (tic) ;

    printf ("time to generate %g million random uint64: %g\n", n, t1) ;
    fprintf (stderr, "time to generate %g million random uint64: %g\n\n",
        n, t1) ;


    free (x) ;
}