Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

628 triangle counting algorithm #190

Open
wants to merge 64 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
06590c0
base blas3::foldl + blas3::foldr API
byjtew May 17, 2023
670e85e
foldl+foldr unit-test
byjtew May 17, 2023
0d3fd9d
Unmasked foldl+foldr implementations in reference
byjtew May 17, 2023
14a380b
parserr bugfix in matrixReduce unit-test
byjtew May 17, 2023
3904c71
Adapt matrixReduce test for OMP foldl+foldr
byjtew May 17, 2023
5c1f559
Adapt base foldl+r signature: operator -> monoid
byjtew May 17, 2023
1cf4e29
reference_omp version of unmasked foldl+r
byjtew May 17, 2023
e5fb254
Extend matrixeReduce unit-test
byjtew May 22, 2023
c1b812f
Remove nested loop for foldl+r, as the order of the reduction is not …
byjtew May 23, 2023
624c193
Documentation review
byjtew Jun 10, 2023
1c09729
Prepare generic folr+l functionfor masked version
byjtew Jun 10, 2023
8ad6be6
Matrix-to-scalar foldl+r masked version
byjtew Jun 10, 2023
8746909
Fuse foldlr_generic and foldl_generic
byjtew Jun 13, 2023
5db9121
Taking into account mask values
byjtew Jun 13, 2023
e6101b9
Separate masked and unmasked versions to benchmark
byjtew Jun 14, 2023
a4bb7a5
Add benchmarking quick to matrixReduce test
byjtew Jun 15, 2023
28599ab
Explicit templates declaration
byjtew Jun 21, 2023
0e59cfa
grb::foldr+l documentation enhancement
byjtew Jun 21, 2023
4a0d635
Implement transpose descriptors in foldl+r
byjtew Jun 21, 2023
3a83956
Implementation of grb::foldl+r in hyperdags
byjtew Jun 21, 2023
fa76769
Restrict foldr+l test to implemented backends
byjtew Jun 21, 2023
b5dd0c5
Add empty+dense mask test cases
byjtew Jun 26, 2023
45589eb
Fix in hyperdags
byjtew Jun 26, 2023
6972be0
Fix masked iteration pattern
byjtew Jun 26, 2023
765d3e3
Add more test cases for masked variant
byjtew Jun 27, 2023
7253d93
Cleaning
byjtew Jun 27, 2023
841aeec
Implementation for BSP1D backend
byjtew Jun 27, 2023
7d5f34c
Implementation in nonblocking (delegating)
byjtew Jun 28, 2023
dccb53b
Cleaning for review
byjtew Jun 28, 2023
218775e
matrixReduce using foldl+foldr unit-test
byjtew May 17, 2023
17b6d7d
parserr bugfix in matrixReduce unit-test
byjtew May 17, 2023
aea630d
Adapt matrixReduce test for OMP foldl+foldr
byjtew May 17, 2023
d80ccf5
Extend matrixeReduce unit-test
byjtew May 22, 2023
96ea3fa
Matrix-to-scalar foldl+r masked version
byjtew Jun 10, 2023
1d30646
Add benchmarking quick to matrixReduce test
byjtew Jun 15, 2023
90380a6
Restrict foldr+l test to implemented backends
byjtew Jun 21, 2023
d6c785d
Add signature for grb::tril in base
byjtew Jun 20, 2023
4d9ba81
Add unit-test for grb::tril
byjtew Jun 20, 2023
fee2add
Implementation of grb::tril for reference+omp
byjtew Jun 20, 2023
725b81f
Implementation of grb::tril for hyperdags
byjtew Jun 20, 2023
ba7c80e
Explicit templates declaration
byjtew Jun 20, 2023
a005d64
More robust test with values verification
byjtew Jun 21, 2023
37c3ef4
Add unit-test for grb::triu
byjtew Jun 21, 2023
aaafcac
Typo in unit-test tril.cpp
byjtew Jun 21, 2023
e0cd596
grb::tril documentation enhancement
byjtew Jun 21, 2023
8ce27af
grb::triu signature and documentation in base
byjtew Jun 21, 2023
ce3a176
grb::triu implementation for reference+omp
byjtew Jun 21, 2023
8efbcbf
Implementation of grb::triu for hyperdags
byjtew Jun 21, 2023
671da32
Triangle counting smoke test
byjtew May 23, 2023
be71215
Triangle counting algorithms - stable
byjtew May 23, 2023
8cef1ab
Test and algorithm signature refactoring
byjtew Jun 10, 2023
22319fb
Check for non-zero values on the diagonal
byjtew Jun 10, 2023
dd8e901
Skip diagonal values while reading matrix
byjtew Jun 10, 2023
dd5f7ee
Adding triangle_count tests for gyro_m & dwt_59
byjtew Jun 10, 2023
888cb3f
Integration of grb::tril+u
byjtew Jun 22, 2023
a89b6eb
Restrict triangle_count test to reference+omp & hyperdags backends
byjtew Jun 22, 2023
9e3007e
Fix triangle_count test verification
byjtew Jun 22, 2023
2ecdf1e
Allow triangle_count test to run on all backends
byjtew Jun 29, 2023
8933de1
Rename algorithm header
byjtew Jun 29, 2023
5064f1b
Cleaning
byjtew Jul 11, 2023
513764d
Merge branch 'develop' into 628-triangle-counting-algorithm
byjtew Feb 9, 2024
331158e
Fix capitalization of include file names
byjtew Feb 9, 2024
194a303
Reveret to a clean state
byjtew Feb 9, 2024
8cf6dec
Revert to a clean state before merging the dependencies
byjtew Feb 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,30 +219,20 @@ install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/interfaces/"

install( TARGETS algorithms EXPORT GraphBLASTargets )

# generate the spblas header with the library prefix
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/transition/spblas.h.in
${CMAKE_CURRENT_BINARY_DIR}/transition/spblas.h @ONLY
)

# this target lists the transition path headers
# these are plain C headers and do not have any dependences
add_library( transition_headers INTERFACE )
add_library( transition INTERFACE )

target_include_directories(
transition_headers INTERFACE
transition INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/transition/>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/transition/>
$<INSTALL_INTERFACE:transition/>
)

install( FILES ${CMAKE_CURRENT_BINARY_DIR}/transition/spblas.h
DESTINATION "${INCLUDE_INSTALL_DIR}/transition"
)

install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/transition/"
DESTINATION "${INCLUDE_INSTALL_DIR}/transition"
DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/../transition/"
FILES_MATCHING REGEX "${HEADERS_REGEX}"
)

install( TARGETS transition_headers EXPORT GraphBLASTargets )
install( TARGETS transition EXPORT GraphBLASTargets )

5 changes: 0 additions & 5 deletions include/graphblas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
* -# generalised sparse linear algebra, \ref GraphBLAS;
* -# vertex-centric programming, \ref Pregel.
*
* Additionally, to ease integration with existing software, ALP defines
* so-called \ref TRANS libraries, which presently includes (partial)
* implementations of the \ref SPARSEBLAS and \ref SPBLAS (de-facto) standards,
* as well as an interface for numerical \ref TRANS_SOLVERS.
*
* Several other programming interfaces are under design at present.
*
* For authors who contributed to ALP, please see the NOTICE file.
Expand Down
24 changes: 11 additions & 13 deletions include/graphblas/algorithms/conjugate_gradient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#define _H_GRB_ALGORITHMS_CONJUGATE_GRADIENT

#include <cstdio>
#include <cmath>
#include <complex>

#include <graphblas.hpp>
#include <graphblas/utils/iscomplex.hpp>
Expand Down Expand Up @@ -144,8 +144,7 @@ namespace grb {
* performance semantics, with the exception of getters such as #grb::nnz, are
* specific to the backend selected during compilation.
*/
template<
Descriptor descr = descriptors::no_operation,
template< Descriptor descr = descriptors::no_operation,
typename IOType,
typename ResidualType,
typename NonzeroType,
Expand All @@ -155,20 +154,19 @@ namespace grb {
grb::identities::zero, grb::identities::one
>,
class Minus = operators::subtract< IOType >,
class Divide = operators::divide< IOType >,
typename RSI, typename NZI, Backend backend
class Divide = operators::divide< IOType >
>
grb::RC conjugate_gradient(
grb::Vector< IOType, backend > &x,
const grb::Matrix< NonzeroType, backend, RSI, RSI, NZI > &A,
const grb::Vector< InputType, backend > &b,
grb::Vector< IOType > &x,
const grb::Matrix< NonzeroType > &A,
const grb::Vector< InputType > &b,
const size_t max_iterations,
ResidualType tol,
size_t &iterations,
ResidualType &residual,
grb::Vector< IOType, backend > &r,
grb::Vector< IOType, backend > &u,
grb::Vector< IOType, backend > &temp,
grb::Vector< IOType > &r,
grb::Vector< IOType > &u,
grb::Vector< IOType > &temp,
const Ring &ring = Ring(),
const Minus &minus = Minus(),
const Divide &divide = Divide()
Expand Down Expand Up @@ -326,7 +324,7 @@ namespace grb {
assert( ret == SUCCESS );

if( ret == SUCCESS ) {
tol *= std::sqrt( grb::utils::is_complex< IOType >::modulus( bnorm ) );
tol *= sqrt( grb::utils::is_complex< IOType >::modulus( bnorm ) );
}

size_t iter = 0;
Expand Down Expand Up @@ -419,7 +417,7 @@ namespace grb {

// return correct error code
if( ret == SUCCESS ) {
if( std::sqrt( residual ) >= tol ) {
if( sqrt( residual ) >= tol ) {
// did not converge within iterations
return FAILED;
}
Expand Down
249 changes: 249 additions & 0 deletions include/graphblas/algorithms/triangle_count.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@

/*
* Copyright 2023 Huawei Technologies Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* @file
*
* Implements the triangle counting algorithm, using different methods.
*
* @author Benjamin Lozes
* @date: May 10th, 2023
*/

#ifndef _H_GRB_TRIANGLE_COUNT
#define _H_GRB_TRIANGLE_COUNT

#include <map>
#include <numeric>
#include <vector>

#include <graphblas/utils/iterators/nonzeroIterator.hpp>

#include <graphblas.hpp>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more empty line here

namespace grb {

namespace algorithms {

enum class TriangleCountAlgorithm { Burkhardt, Cohen, Sandia_TT };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doxy comment missing -- may be nice to add the references for each variant in the doxy


std::map< TriangleCountAlgorithm, std::string > TriangleCountAlgorithmNames = {
{ TriangleCountAlgorithm::Burkhardt, "Burkhardt" },
{ TriangleCountAlgorithm::Cohen, "Cohen" },
{ TriangleCountAlgorithm::Sandia_TT, "Sandia_TT" }
};
Comment on lines +44 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should move into a namespace internal ?


template<
class Semiring, class MulMonoid, class SumMonoid,
Descriptor descr_mxm = descriptors::no_operation,
Descriptor descr_ewa = descriptors::no_operation,
Descriptor descr_reduce = descriptors::no_operation,
typename D1, typename RIT1, typename CIT1, typename NIT1,
typename D2, typename RIT2, typename CIT2, typename NIT2,
typename D3, typename RIT3, typename CIT3, typename NIT3,
typename D4, typename RIT4, typename CIT4, typename NIT4,
typename D5, typename RIT5, typename CIT5, typename NIT5,
typename D6
>
RC triangle_count_generic(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably also go into a namespace internal?

size_t & count,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no space after &

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(below args also)

Matrix< D1, config::default_backend, RIT1, CIT1, NIT1 > & MXM_out,
const Matrix< D2, config::default_backend, RIT2, CIT2, NIT2 > & MXM_lhs,
const Matrix< D3, config::default_backend, RIT3, CIT3, NIT3 > & MXM_rhs,
Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & EWA_out,
const Matrix< D5, config::default_backend, RIT5, CIT5, NIT5 > & EWA_rhs,
const D6 div_factor,
const Semiring mxm_semiring = Semiring(),
const MulMonoid ewiseapply_monoid = MulMonoid(),
const SumMonoid sumreduce_monoid = SumMonoid()
) {
if( ( &MXM_out == &MXM_lhs ) || ( &MXM_out == &MXM_rhs ) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use getID for this check instead?

return ILLEGAL;
}

RC rc = SUCCESS;

// Compute MXM_out = Mlhs * Mrhs
rc = rc ? rc : mxm< descr_mxm >( MXM_out, MXM_lhs, MXM_rhs, mxm_semiring, Phase::RESIZE );
rc = rc ? rc : mxm< descr_mxm >( MXM_out, MXM_lhs, MXM_rhs, mxm_semiring, Phase::EXECUTE );

// Compute MXM_out .*= EWA_rhs
// FIXME: Replace by a foldl( Matrix[in,out], Matrix[in], Monoid ) - not implemented yet
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does an issue exist to provide it?

// Will then become:
// rc = rc ? rc : eWiseApply< descr_ewa >( MXM_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::RESIZE );
// rc = rc ? rc : eWiseApply< descr_ewa >( MXM_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::EXECUTE );
Comment on lines +87 to +88
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eWiseApply -> foldl and remove one of the duplicate MXM_out arguments?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if replacing it with foldl, then a clear on MXM_out becomes mandatory right?

// Instead of:
rc = rc ? rc : eWiseApply< descr_ewa >( EWA_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::RESIZE );
rc = rc ? rc : eWiseApply< descr_ewa >( EWA_out, MXM_out, EWA_rhs, ewiseapply_monoid, Phase::EXECUTE );

// Compute a sum reduction over <EWA_out> into <count>
count = static_cast< size_t >( 0 );
rc = rc ? rc : foldl< descr_reduce >( count, EWA_out, sumreduce_monoid );

// Apply the div_factor to the reduction result
count /= div_factor;

return rc;
}

/**
* Given a graph, indicates how many triangles are contained within.
*
* @tparam D The type of the matrix non-zero values.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alignment should be done with spaces (the white space between D and The currently are tabs)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(below also)

*
* @param[out] count The number of triangles.
* Any prior contents will be ignored.
* @param[in] A The input graph.
* @param[in,out] MXM_out Buffer matrix with the same dimensions as the input
* graph. Any prior contents will be ignored.
Comment on lines +110 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't say A and MXM_out cannot be the same matrix (that restriction should be added:)

* @param[in] L Lower triangular matrix of the input graph (optional)
* @param[in] U Lower triangular matrix of the input graph (optional)
*
*
* @returns #grb::SUCCESS When the computation completes successfully.
* @returns #grb::MISMATCH If the dimensions of the input matrices/buffers
* are incompatible.
* @returns #grb::ILLEGAL If the given algorithm does not exist.
* @returns #grb::PANIC If an unrecoverable error has been encountered. The
* output as well as the state of ALP/GraphBLAS is
* undefined.
*
* \par Performance semantics
*
* -# This function does not allocate nor free dynamic memory, nor shall it
* make any system calls.
*
Comment on lines +127 to +129
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a resize phase which can actually dynamically allocate memory. Therefore, the #grb::OUT_OF_MEMORY error code should be added to the directly preceding list of return options, where the highlighted text here should mention that the performance here strongly depends on the sparsity structure, which affects all of work, data movement, and memory usage costs. The only thing that is kept constant in all algorithms is the number of synchronisations needed in case there are more than 1 user processes-- namely, those required for one mxm, one eWiseApply (or foldl), and one reduction. ("For BSP1D, this amounts to 2 synchronisations." could be added as a \note)

* For performance semantics regarding work, inter-process data movement,
* intra-process data movement, synchronisations, and memory use, please see
* the specification of the ALP primitives this function relies on. These
* performance semantics, with the exception of getters such as #grb::nnz, are
* specific to the backend selected during compilation.
*/
template<
Descriptor descr = descriptors::no_operation,
typename D1, typename RIT1, typename CIT1, typename NIT1,
typename D2, typename RIT2, typename CIT2, typename NIT2,
typename D3, typename RIT3, typename CIT3, typename NIT3,
typename D4, typename RIT4, typename CIT4, typename NIT4,
class Semiring = Semiring< operators::add< D1 >,
operators::mul< D1 >,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many tabs (below also)

identities::zero,
identities::one >,
class MulMonoid = Monoid< operators::mul< D1 >,
identities::one >,
class SumMonoid = Monoid< operators::add< size_t, D1, size_t >,
identities::zero >
>
RC triangle_count(
const TriangleCountAlgorithm algo,
size_t & count,
const Matrix< D1, config::default_backend, RIT1, CIT1, NIT1 > & A,
Matrix< D2, config::default_backend, RIT2, CIT2, NIT2 > & MXM_out,
Matrix< D3, config::default_backend, RIT3, CIT3, NIT3 > & EWA_out,
Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & L = { 0, 0 },
Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & U = { 0, 0 }
) {
// Static assertions
static_assert( std::is_integral< D1 >::value, "Type D1 must be integral" );

// Sanity checks
if( nrows( A ) != ncols( A ) ) {
std::cerr << "Matrix A must be square" << std::endl;
return MISMATCH;
}
if( ncols( L ) != nrows( L ) ) {
std::cerr << "Matrix L must be square" << std::endl;
return MISMATCH;
}
if( nrows( A ) != ncols( L ) ) {
std::cerr << "Matrices A and L must have the same dimensions" << std::endl;
return MISMATCH;
}
if( ncols( U ) != nrows( U ) ) {
std::cerr << "Matrix U must be square" << std::endl;
return MISMATCH;
}
if( nrows( A ) != ncols( U ) ) {
std::cerr << "Matrices A and U must have the same dimensions" << std::endl;
return MISMATCH;
}
if( ncols( MXM_out ) != nrows( MXM_out ) ) {
std::cerr << "Matrix MXM_out must be square" << std::endl;
return MISMATCH;
}
if( nrows( A ) != ncols( MXM_out ) ) {
std::cerr << "Matrices A and MXM_out must have the same dimensions" << std::endl;
return MISMATCH;
}
if( ncols( EWA_out ) != nrows( EWA_out ) ) {
std::cerr << "Matrix EWA_out must be square" << std::endl;
return MISMATCH;
}
if( nrows( A ) != ncols( EWA_out ) ) {
std::cerr << "Matrices A and EWA_out must have the same dimensions" << std::endl;
return MISMATCH;
}

// Dispatch to the appropriate algorithm
switch( algo ) {
case TriangleCountAlgorithm::Burkhardt: {
return triangle_count_generic<
Semiring, MulMonoid, SumMonoid,
descr | descriptors::transpose_right
>( count, MXM_out, A, A, EWA_out, A, 6UL );
}

case TriangleCountAlgorithm::Cohen: {
if( nrows( L ) == 0 || ncols( L ) == 0 ) {
std::cerr << "Matrix L must be provided for the Cohen algorithm" << std::endl;
return MISMATCH;
}
if( nrows( U ) == 0 || ncols( U ) == 0 ) {
std::cerr << "Matrix U must be provided for the Cohen algorithm" << std::endl;
return MISMATCH;
}

return triangle_count_generic<
Semiring, MulMonoid, SumMonoid
>( count, MXM_out, L, U, EWA_out, A, 2UL );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space before A

}

case TriangleCountAlgorithm::Sandia_TT: {
if( ( nrows( U ) == 0 || ncols( U ) == 0 ) && ( nrows( L ) == 0 || ncols( L ) == 0 ) ) {
std::cerr << "Matrix L or U must be provided for the Sandia_TT algorithm" << std::endl;
return MISMATCH;
}

const Matrix< D4, config::default_backend, RIT4, CIT4, NIT4 > & T = ( nrows( U ) == 0 || ncols( U ) == 0 ) ? L : U;
return triangle_count_generic<
Semiring, MulMonoid, SumMonoid
>( count, MXM_out, T, T, EWA_out, T, 1UL );
}

default:
std::cerr << "Unknown TriangleCountAlgorithm enum value" << std::endl;
return ILLEGAL;
}

return SUCCESS;
}

} // namespace algorithms

} // namespace grb

#endif // _H_GRB_TRIANGLE_COUNT
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing empty line at the end here

Loading
Loading