Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 18 additions & 7 deletions include/graphblas/algorithms/label.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ namespace grb {
* accelerating the PageRank computation', ACM Press, 2003.
*/
template< typename IOType >
RC label( Vector< IOType > &out,
RC label(
Vector< IOType > &out,
const Vector< IOType > &y, const Matrix< IOType > &W,
const size_t n, const size_t l,
const size_t MaxIterations = 1000
Expand Down Expand Up @@ -230,7 +231,12 @@ namespace grb {
<< "nnz( mask ) = " << nnz( mask ) << "\n";
#endif
// clamps the first l labelled nodes
ret = ret ? ret : set( fNext, mask, f );
ret = ret ? ret : foldl(
fNext, mask,
f,
grb::operators::right_assign< IOType >()
);
assert( ret == SUCCESS );
#ifdef _DEBUG
std::cerr << "\t post-set nnz( fNext ) = " << nnz( fNext ) << "\n";
printVector(
Expand All @@ -246,31 +252,36 @@ namespace grb {
#ifdef _DEBUG
std::cerr << "\t pre-set nnz(f) = " << nnz( f ) << "\n";
#endif
ret = ret ? ret : set( f, fNext );
std::swap( f, fNext );
#ifdef _DEBUG
std::cerr << "\t post-set nnz(f) = " << nnz( f ) << "\n";
#endif
// go to next iteration
(void)++iter;
(void) ++iter;
}

if( ret == SUCCESS ) {
if( different ) {
if( s == 0 ) {
std::cout << "Warning: label propagation did not converge after "
std::cerr << "Info: label propagation did not converge after "
<< (iter-1) << " iterations\n";
}
return FAILED;
} else {
if( s == 0 ) {
std::cout << "Info: label propagation converged in "
std::cerr << "Info: label propagation converged in "
<< (iter-1) << " iterations\n";
}
return set( out, f );
std::swap( out, f );
return SUCCESS;
}
}

// done
if( s == 0 ) {
std::cerr << "Warning: label propagation exiting with " << toString(ret)
<< "\n";
}
return ret;
}

Expand Down
178 changes: 175 additions & 3 deletions include/graphblas/bsp1d/blas1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,178 @@ namespace grb {
return ret;
}

/** \internal No implementation notes */
template<
Descriptor descr = descriptors::no_operation, class OP,
typename IOType, typename MaskType, typename InputType,
typename Coords
>
RC foldl(
Vector< IOType, BSP1D, Coords > &x,
const Vector< MaskType, BSP1D, Coords > &m,
const Vector< InputType, BSP1D, Coords > &y,
const OP &op = OP(),
const Phase &phase = EXECUTE,
const typename std::enable_if< grb::is_operator< OP >::value &&
!grb::is_object< IOType >::value &&
!grb::is_object< MaskType >::value &&
!grb::is_object< InputType >::value, void
>::type * = nullptr
) {
// static sanity checks
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename OP::D1, IOType >::value ),
"grb::foldl",
"called with a vector x of a type that does not match the first domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename OP::D2, InputType >::value ),
"grb::foldl",
"called on a vector y of a type that does not match the second domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename OP::D3, IOType >::value ),
"grb::foldl",
"called on a vector x of a type that does not match the third domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< bool, MaskType >::value ),
"grb::foldl",
"called with a mask that does not have boolean entries " );

// catch empty mask
if( size( m ) == 0 ) {
return foldl< descr >( x, y, op, phase );
}

// dynamic sanity checks
const size_t n = size( x );
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}

// handle trivial resize phase
if( config::IMPLEMENTATION< BSP1D >::fixedVectorCapacities() &&
phase == RESIZE
) {
return SUCCESS;
}

// delegate
RC ret = foldl< descr >(
internal::getLocal( x ), internal::getLocal( m ),
internal::getLocal( y ),
op, phase
);

if( !config::IMPLEMENTATION< BSP1D >::fixedVectorCapacities() ) {
if( collectives< BSP1D >::allreduce(
ret, grb::operators::any_or< RC >()
) != SUCCESS ) {
return PANIC;
}
}

// handle try and execute phases
if( phase != RESIZE ) {
if( ret == SUCCESS ) {
ret = internal::updateNnz( x );
} else if( ret == FAILED ) {
const RC subrc = internal::updateNnz( x );
if( subrc != SUCCESS ) { ret = PANIC; }
}
}

// done
return ret;
}

/** \internal No implementation notes */
template<
Descriptor descr = descriptors::no_operation, class Monoid,
typename IOType, typename MaskType, typename InputType,
typename Coords
>
RC foldl(
Vector< IOType, BSP1D, Coords > &x,
const Vector< MaskType, BSP1D, Coords > &m,
const Vector< InputType, BSP1D, Coords > &y,
const Monoid &monoid = Monoid(),
const Phase &phase = EXECUTE,
const typename std::enable_if< grb::is_monoid< Monoid >::value &&
!grb::is_object< IOType >::value &&
!grb::is_object< MaskType >::value &&
!grb::is_object< InputType >::value, void
>::type * = nullptr
) {
// static sanity checks
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename Monoid::D1, IOType >::value ),
"grb::foldl",
"called with a vector x of a type that does not match the first domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename Monoid::D2, InputType >::value ),
"grb::foldl",
"called on a vector y of a type that does not match the second domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< typename Monoid::D3, IOType >::value ),
"grb::foldl",
"called on a vector x of a type that does not match the third domain "
"of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< bool, MaskType >::value ),
"grb::foldl",
"called with a mask that does not have boolean entries" );

// catch empty mask
if( size( m ) == 0 ) {
return foldl< descr >( x, y, monoid, phase );
}

// dynamic sanity checks
const size_t n = size( x );
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}

// handle trivial resize phase
if( config::IMPLEMENTATION< BSP1D >::fixedVectorCapacities() &&
phase == RESIZE
) {
return SUCCESS;
}

// delegate
RC ret = foldl< descr >(
internal::getLocal( x ), internal::getLocal( m ),
internal::getLocal( y ),
monoid, phase
);

if( !config::IMPLEMENTATION< BSP1D >::fixedVectorCapacities() ) {
if( collectives< BSP1D >::allreduce(
ret, grb::operators::any_or< RC >()
) != SUCCESS ) {
return PANIC;
}
}

// handle try and execute phases
if( phase != RESIZE ) {
if( ret == SUCCESS ) {
ret = internal::updateNnz( x );
} else if( ret == FAILED ) {
const RC subrc = internal::updateNnz( x );
if( subrc != SUCCESS ) { ret = PANIC; }
}
}

// done
return ret;
}

/** \internal No communication necessary, output is guaranteed dense. */
template<
Descriptor descr = descriptors::no_operation,
Expand All @@ -683,17 +855,17 @@ namespace grb {

// static checks
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< InputType1, typename Operator::D1 >::value ),
std::is_same< InputType1, typename Operator::D1 >::value ),
"grb::eWiseApply",
"called with a left-hand input vector value type that does not match the "
"first domain of the given operator " );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< InputType2, typename Operator::D2 >::value ),
std::is_same< InputType2, typename Operator::D2 >::value ),
"grb::eWiseApply",
"called with a right-hand input vector value type that does not match the second "
"domain of the given operator" );
NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) ||
std::is_same< OutputType, typename Operator::D3 >::value ),
std::is_same< OutputType, typename Operator::D3 >::value ),
"grb::eWiseApply",
"called with an output value type that does not match the third domain of "
"the given operator" );
Expand Down
13 changes: 9 additions & 4 deletions include/graphblas/descriptors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,11 @@ namespace grb {
static constexpr Descriptor structural_complement = structural | invert_mask;

/**
* Indicates that all input vectors to an ALP/GraphBLAS primitive are
* structurally dense.
* Indicates that all input and output vectors to an ALP/GraphBLAS primitive
* are structurally dense.
*
* If a user passes this descriptor but one or more vectors input to the call
* are \em not structurally dense, then #ILLEGAL shall be returned.
* If a user passes this descriptor but one or more vectors to the call are
* \em not structurally dense, then #ILLEGAL shall be returned.
*
* \warning <em>All vectors</em> includes any vectors that operate as masks.
* Thus if the primitive is to operate with structurally sparse masks
Expand All @@ -134,13 +134,18 @@ namespace grb {
* passing this descriptor to such primitive indicates that also the
* output vector is structurally dense.
*
* \warning For out-of-place operations with vector output(s), passing this
* descriptor also demands that the output vectors are already
* dense.
*
* \warning Vectors with explicit zeroes (under the semiring passed to the
* related primitive) will be computed with explicitly.
*
* The benefits of using this descriptor whenever possible are two-fold:
* 1) less run-time overhead as code handling sparsity is disabled;
* 2) smaller binary sizes as code handling structurally sparse vectors is
* not emitted (unless required elsewhere).
*
* The consistent use of this descriptor is hence strongly encouraged.
*/
static constexpr Descriptor dense = 16;
Expand Down
34 changes: 31 additions & 3 deletions include/graphblas/reference/blas1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1058,9 +1058,6 @@ namespace grb {
if( !sparse && nnz( to_fold ) < n ) {
return ILLEGAL;
}
if( masked && !sparse && nnz( *m ) < n ) {
return ILLEGAL;
}
if( phase == RESIZE ) {
return SUCCESS;
}
Expand Down Expand Up @@ -1852,6 +1849,12 @@ namespace grb {
return MISMATCH;
}

const size_t n = size( x );

if( descr & descriptors::dense ) {
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

#ifdef _DEBUG
std::cout << "In foldr ([T]<-[T])\n";
#endif
Expand Down Expand Up @@ -1919,6 +1922,10 @@ namespace grb {
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( size( m ) > 0 && nnz( m ) != n ) { return ILLEGAL; }
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

if( nnz( x ) < n || nnz( y ) < n ) {
return internal::fold_from_vector_to_vector_generic<
Expand Down Expand Up @@ -2036,6 +2043,9 @@ namespace grb {
if( n != size( y ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

const Vector< bool, reference, Coords > * const null_mask = nullptr;
if( nnz( x ) < n || nnz( y ) < n ) {
Expand Down Expand Up @@ -2101,6 +2111,10 @@ namespace grb {
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( size( m ) > 0 && nnz( m ) != n ) { return ILLEGAL; }
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

if( nnz( x ) < n || nnz( y ) < n ) {
return internal::fold_from_vector_to_vector_generic<
Expand Down Expand Up @@ -2580,6 +2594,9 @@ namespace grb {
if( n != size( y ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

// all OK, execute
const Vector< bool, reference, Coords > * const null_mask = nullptr;
Expand Down Expand Up @@ -2703,6 +2720,9 @@ namespace grb {
if( n != size( y ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

// all OK, execute
const Vector< bool, reference, Coords > * const null_mask = nullptr;
Expand Down Expand Up @@ -2771,6 +2791,10 @@ namespace grb {
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( size( m ) > 0 && nnz( m ) != n ) { return ILLEGAL; }
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

// all OK, execute
if( nnz( x ) < n || nnz( y ) < n ) {
Expand Down Expand Up @@ -2838,6 +2862,10 @@ namespace grb {
if( n != size( y ) || n != size( m ) ) {
return MISMATCH;
}
if( descr & descriptors::dense ) {
if( size( m ) > 0 && nnz( m ) != n ) { return ILLEGAL; }
if( nnz( x ) != n || nnz( y ) != n ) { return ILLEGAL; }
}

// all OK, execute
if( nnz( x ) < n || nnz( y ) < n ) {
Expand Down
Loading