Skip to content

Commit

Permalink
v7.3.0 (beta4): change hyperhash to uint64, check for no change in A-…
Browse files Browse the repository at this point in the history
…>Y in GB_wait
  • Loading branch information
DrTimothyAldenDavis committed Sep 5, 2022
1 parent 441f99f commit 9992f75
Show file tree
Hide file tree
Showing 17 changed files with 251 additions and 317 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ message ( STATUS "GrapphBLAS build: " ${CMAKE_BINARY_DIR} )
message ( STATUS "CMake version: " ${CMAKE_VERSION} )

# version of SuiteSparse:GraphBLAS
set ( GraphBLAS_DATE "Sept 2, 2022 (beta3)" ) # FIXME
set ( GraphBLAS_DATE "Sept 5, 2022 (beta4)" ) # FIXME
set ( GraphBLAS_VERSION_MAJOR 7 )
set ( GraphBLAS_VERSION_MINOR 3 )
set ( GraphBLAS_VERSION_SUB 0 )
Expand Down
2 changes: 1 addition & 1 deletion Doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Version 7.3.0, Sept 2, 2022
Version 7.3.0, Sept 5, 2022

* GrB_Matrix: changes to the internal data structure
* minor internal changes: A->nvals for sparse/hypersparse
Expand Down
Binary file modified Doc/GraphBLAS_UserGuide.pdf
Binary file not shown.
4 changes: 3 additions & 1 deletion Doc/GraphBLAS_UserGuide.tex
Original file line number Diff line number Diff line change
Expand Up @@ -15449,14 +15449,16 @@ \section{Release Notes}

\begin{itemize}

\item Version 7.3.0 (Aug 30, 2022)
\item Version 7.3.0 (Sept 5, 2022)

\begin{packed_itemize}
\item \verb'GrB_Matrix': changes to the internal data structure
\item minor internal changes: \verb'A->nvals' for sparse/hypersparse
\item more significant changes: added hyper-hash for
hypersparse case, speeds up many operations on hypersparse matrices.
Based on \cite{Green19}.
\item \verb'GxB_unpack_HyperHash' and \verb'GxB_pack_HyperHash':
to pack/unpack the hyper-hash
\item \verb'@GrB' MATLAB/Octave interface: changed license to Apache-2.0.
\end{packed_itemize}

Expand Down
2 changes: 1 addition & 1 deletion Doc/GraphBLAS_version.tex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
% version of SuiteSparse:GraphBLAS
\date{VERSION
7.3.0,
Sept 2, 2022 (beta3)}
Sept 5, 2022 (beta4)}

9 changes: 2 additions & 7 deletions GraphBLAS/@GrB/private/util/gb_export_to_mxstruct.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,8 @@ mxArray *gb_export_to_mxstruct // return exported built-in struct G
case GxB_HYPERSPARSE :

// export and free the A->Y hyper_hash. It is always sparse,
// GrB_INT64, held by column, and non-iso
// printf ("unpacking hypersparse A\n") ;
// OK (GxB_print (A, 2)) ;
// GrB_UINT64, held by column, and non-iso
OK (GxB_unpack_HyperHash (A, &Y, NULL)) ;
// printf ("did unpacking hypersparse A\n") ;
// OK (GxB_print (A, 2)) ;
// OK (GxB_print (Y, 2)) ;
OK (GxB_Matrix_export_CSC (&Y, &ytype, &ynrows, &yvdim,
&Yp, &Yi, &Yx, &Yp_size, &Yi_size, &Yx_size,
NULL, NULL, NULL)) ;
Expand Down Expand Up @@ -328,7 +323,7 @@ mxArray *gb_export_to_mxstruct // return exported built-in struct G
mxSetFieldByNumber (G, 0, 7, Yi_mx) ;

// export Yx, of size nvec
mxArray *Yx_mx = mxCreateNumericMatrix (1, 0, mxINT64_CLASS, mxREAL) ;
mxArray *Yx_mx = mxCreateNumericMatrix (1, 0, mxUINT64_CLASS, mxREAL) ;
mxSetN (Yx_mx, nvec) ;
p = (void *) mxGetData (Yx_mx) ; gb_mxfree (&p) ;
mxSetData (Yx_mx, Yx) ;
Expand Down
6 changes: 2 additions & 4 deletions GraphBLAS/@GrB/private/util/gb_get_shallow.c
Original file line number Diff line number Diff line change
Expand Up @@ -350,16 +350,14 @@ GrB_Matrix gb_get_shallow // return a shallow copy of built-in sparse matrix

if (yvdim > 0)
{
// A->Y is sparse, type is int64, (A->vdim)-by-yvdim, held by column
OK (GrB_Matrix_new (&Y, GrB_INT64, vdim, yvdim)) ;
// A->Y is sparse, uint64, (A->vdim)-by-yvdim, held by column
OK (GrB_Matrix_new (&Y, GrB_UINT64, vdim, yvdim)) ;
OK (GxB_Matrix_Option_set (Y, GxB_FORMAT, GxB_BY_COL)) ;
OK (GxB_Matrix_pack_CSC (Y,
&Yp, &Yi, &Yx, Yp_size, Yi_size, Yx_size, false,
false, NULL)) ;
OK (GxB_Matrix_Option_set (Y, GxB_SPARSITY_CONTROL, GxB_SPARSE)) ;
// OK (GxB_print (Y, 2)) ;
OK (GxB_pack_HyperHash (A, &Y, NULL)) ;
// OK (GxB_print (A, 2)) ;
}

// tell GraphBLAS the matrix is shallow
Expand Down
2 changes: 1 addition & 1 deletion GraphBLAS/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ message ( STATUS "CMake version: " ${CMAKE_VERSION} )
# version must match ../CMakeLists.txt:

# version of SuiteSparse:GraphBLAS
set ( GraphBLAS_DATE "Sept 2, 2022 (beta3)" ) # FIXME
set ( GraphBLAS_DATE "Sept 5, 2022 (beta4)" ) # FIXME
set ( GraphBLAS_VERSION_MAJOR 7 )
set ( GraphBLAS_VERSION_MINOR 3 )
set ( GraphBLAS_VERSION_SUB 0 )
Expand Down
2 changes: 1 addition & 1 deletion Include/GraphBLAS.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@

// The version of this implementation, and the GraphBLAS API version:
#define GxB_IMPLEMENTATION_NAME "SuiteSparse:GraphBLAS"
#define GxB_IMPLEMENTATION_DATE "Sept 2, 2022 (beta3)"
#define GxB_IMPLEMENTATION_DATE "Sept 5, 2022 (beta4)"
#define GxB_IMPLEMENTATION_MAJOR 7
#define GxB_IMPLEMENTATION_MINOR 3
#define GxB_IMPLEMENTATION_SUB 0
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.

SPDX-License-Identifier: Apache-2.0

VERSION 7.3.0, Sept 2, 2022 (beta3)
VERSION 7.3.0, Sept 5, 2022 (beta4)

SuiteSparse:GraphBLAS is a complete implementation of the GraphBLAS standard,
which defines a set of sparse matrix operations on an extended algebra of
Expand Down
12 changes: 6 additions & 6 deletions Source/GB_hyper_hash_build.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed
GrB_Info info ;
int64_t *restrict I_work = NULL ; size_t I_work_size = 0 ;
int64_t *restrict J_work = NULL ; size_t J_work_size = 0 ;
int64_t *restrict X_work = NULL ; size_t X_work_size = 0 ;
uint64_t *restrict X_work = NULL ; size_t X_work_size = 0 ;

ASSERT_MATRIX_OK (A, "A for hyper_hash", GB0) ;
GB_BURBLE_MATRIX (A, "(build hyper hash) ") ;
Expand All @@ -66,7 +66,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed
int64_t hash_bits = (yvdim - 1) ; // yvdim is always a power of 2

GB_OK (GB_new (&(A->Y), // new dynamic header, do not allocate any content
GrB_INT64, yvlen, yvdim, GB_Ap_null, true, GxB_SPARSE,
GrB_UINT64, yvlen, yvdim, GB_Ap_null, true, GxB_SPARSE,
-1, 0, Context)) ;
GrB_Matrix Y = A->Y ;

Expand All @@ -76,7 +76,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed

I_work = GB_MALLOC (anvec, int64_t, &I_work_size) ;
J_work = GB_MALLOC (anvec, int64_t, &J_work_size) ;
X_work = GB_MALLOC (anvec, int64_t, &X_work_size) ;
X_work = GB_MALLOC (anvec, uint64_t, &X_work_size) ;
if (I_work == NULL || J_work == NULL || X_work == NULL)
{
// out of memory
Expand All @@ -94,7 +94,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed
int64_t j = Ah [k] ;
I_work [k] = j ;
J_work [k] = GB_HASHF2 (j, hash_bits) ; // in range 0 to yvdim-1
X_work [k] = k ;
X_work [k] = (uint64_t) k ;
}

//--------------------------------------------------------------------------
Expand All @@ -103,7 +103,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed

GB_OK (GB_builder (
Y, // create Y using a dynamic header
GrB_INT64, // Y->type
GrB_UINT64, // Y->type
yvlen, // Y->vlen
yvdim, // Y->vdim
true, // Y->is_csc
Expand All @@ -122,7 +122,7 @@ GrB_Info GB_hyper_hash_build // construct A->Y if not already constructed
false, // Y is never iso
anvec, // # of tuples
NULL, // no duplicates, so dup is NUL
GrB_INT64, // the type of X_work
GrB_UINT64, // the type of X_work
false, // no burble (already burbled above)
Context
)) ;
Expand Down
8 changes: 4 additions & 4 deletions Source/GB_matvec_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,12 +850,12 @@ GrB_Info GB_matvec_check // check a GraphBLAS matrix or vector
return (info) ;
}
if (Y->vlen != A->vdim || !GB_IS_POWER_OF_TWO (Y->vdim) ||
Y->nvals != A->nvec || !GB_IS_SPARSE (Y) || Y->type != GrB_INT64 ||
Y->nvals != A->nvec || !GB_IS_SPARSE (Y) || Y->type != GrB_UINT64 ||
!Y->is_csc || GB_ANY_PENDING_WORK (Y))
{
// Y must be sparse, int64, held by column, with A->nvec values,
// vector length the same as A->vdim, and with a Y->vdim that is
// a power of 2. It cannot have any pending work.
// Y must be sparse, uint64, held by column, with A->nvec values,
// vector length the same as A->vdim, and with a Y->vdim that is a
// power of 2. It cannot have any pending work.
GBPR0 (" hyper_hash invalid") ;
return (GrB_INVALID_OBJECT) ;
}
Expand Down
95 changes: 87 additions & 8 deletions Source/GB_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,26 @@

// If the method is successful, it does an OpenMP flush just before returning.

#define GB_FREE_ALL \
#define GB_FREE_WORKSPACE \
{ \
GB_phybix_free (A) ; \
GB_Matrix_free (&Y) ; \
GB_Matrix_free (&T) ; \
GB_Matrix_free (&S) ; \
GB_Matrix_free (&A1) ; \
}

#define GB_FREE_ALL \
{ \
GB_FREE_WORKSPACE ; \
GB_phybix_free (A) ; \
}

#include "GB_select.h"
#include "GB_add.h"
#include "GB_Pending.h"
#include "GB_build.h"
#include "GB_jappend.h"
#include "GB_atomics.h"

GB_PUBLIC
GrB_Info GB_wait // finish all pending computations
Expand All @@ -64,7 +71,7 @@ GrB_Info GB_wait // finish all pending computations

GrB_Info info = GrB_SUCCESS ;
struct GB_Matrix_opaque T_header, A1_header, S_header ;
GrB_Matrix T = NULL, A1 = NULL, S = NULL ;
GrB_Matrix T = NULL, A1 = NULL, S = NULL, Y = NULL ;

ASSERT_MATRIX_OK (A, "A to wait", GB_FLIP (GB0)) ;

Expand Down Expand Up @@ -518,7 +525,8 @@ GrB_Info GB_wait // finish all pending computations
GB_Matrix_free (&T) ;

// conform A to its desired sparsity structure
info = GB_conform (A, Context) ;
GB_OK (GB_conform (A, Context)) ;
ASSERT (A->nvec_nonempty >= 0) ;

}
else
Expand All @@ -539,22 +547,93 @@ GrB_Info GB_wait // finish all pending computations
// T->Y is not present (GB_builder does not create it). The old A->Y
// is still valid, if present, for the matrix A prior to added the
// pending tuples in T. GB_add may need A->Y to compute S, but it does
// not compute S->Y. The old A->Y is freed by the transplant. On
// output, after the transplant, the new A has no A->Y hyper_hash.
// not compute S->Y.

GB_CLEAR_STATIC_HEADER (S, &S_header) ;
GB_OK (GB_add (S, A->type, A->is_csc, NULL, 0, 0, &ignore, A, T,
false, NULL, NULL, NULL, Context)) ;
GB_Matrix_free (&T) ;
ASSERT_MATRIX_OK (S, "S after GB_wait:add", GB0) ;
info = GB_transplant_conform (A, A->type, &S, Context) ;

if (GB_IS_HYPERSPARSE (A) && GB_IS_HYPERSPARSE (S) && A->Y != NULL
&& !A->Y_shallow && !GB_is_shallow (A->Y))
{
// A and S are both hypersparse, and the old A->Y exists and is not
// shallow. Check if S->h and A->h are identical. If so, remove
// A->Y from A and save it. Then after the transplant of S into A,
// below, if A is still hyperparse, transplant Y back into A->Y.
if (S->nvec == anvec)
{
// A and S have the same number of vectors. Compare Ah and Sh
int64_t *restrict Ah = A->h ;
int64_t *restrict Sh = S->h ;
bool hsame = true ;
int nthreads = GB_nthreads (anvec, chunk, nthreads_max) ;
if (nthreads == 1)
{
// compare Ah and Sh with a single thread
hsame = (memcmp (Ah, Sh, anvec * sizeof (int64_t)) == 0) ;
}
else
{
// compare Ah and Sh with several threads
int ntasks = 64 * nthreads ;
int tid ;
#pragma omp parallel for num_threads(nthreads) \
schedule(dynamic)
for (tid = 0 ; tid < ntasks ; tid++)
{
int64_t kstart, kend ;
GB_PARTITION (kstart, kend, anvec, tid, ntasks) ;
bool my_hsame ;
GB_ATOMIC_READ
my_hsame = hsame ;
if (my_hsame)
{
// compare my region of Ah and Sh
my_hsame = (memcmp (Ah + kstart, Sh + kstart,
(kend - kstart) * sizeof (int64_t)) == 0) ;
if (!my_hsame)
{
// tell other tasks to exit early
GB_ATOMIC_WRITE
hsame = false ;
}
}
}
}
if (hsame)
{
// Ah and Sh are the same, so keep A->Y
Y = A->Y ;
A->Y = NULL ;
A->Y_shallow = false ;
}
}
}

// transplant S into A
GB_OK (GB_transplant_conform (A, A->type, &S, Context)) ;
ASSERT (A->nvec_nonempty >= 0) ;

if (Y != NULL && GB_IS_HYPERSPARSE (A) && A->Y == NULL)
{
// The hyperlist of A has not changed. A is still hypersparse, and
// has no A->Y after the transplant/conform above. The original
// A->Y is valid, so transplant it back into A.
A->Y = Y ;
A->Y_shallow = false ;
Y = NULL ;
}

ASSERT_MATRIX_OK (A, "A after GB_wait:add", GB0) ;
}

//--------------------------------------------------------------------------
// flush the matrix and return result
//--------------------------------------------------------------------------

ASSERT (GB_IMPLIES (info == GrB_SUCCESS, A->nvec_nonempty >= 0)) ;
GB_FREE_WORKSPACE ;
#pragma omp flush
return (info) ;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/GxB_pack_HyperHash.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ GrB_Info GxB_pack_HyperHash // move Y into A->Y

if ((*Y)->vlen != A->vdim || !GB_IS_POWER_OF_TWO ((*Y)->vdim) ||
(*Y)->nvals != A->nvec || !GB_IS_SPARSE (*Y) || (*Y)->Y != NULL ||
(*Y)->type != GrB_INT64 || !(*Y)->is_csc || GB_ANY_PENDING_WORK (*Y))
(*Y)->type != GrB_UINT64 || !(*Y)->is_csc || GB_ANY_PENDING_WORK (*Y))
{
// Y is invalid
return (GrB_INVALID_OBJECT) ;
Expand Down
Loading

0 comments on commit 9992f75

Please sign in to comment.