Skip to content

Commit

Permalink
338 request for fuselets (#339)
Browse files Browse the repository at this point in the history
This MR provides so-called _fuselets_.

Fuselets are sequences of operations that may occur in existing code bases, and could be accelerated using the nonblocking backend. A fuselet represents such a sequence of operations, which are exposed as a single plain-C function call. ALP during its standard build will generate a library of those fuselets using its nonblocking backend, thus resulting in high-performance, automatically fused kernels.

The fuselets furthermore, at run-time and again automatically, tunes performance parameters such as tile sizes and the number of threads to be used.

Finally, the example fuselets provided in `include/transition/fuselets.h` and `src/transition/fuselets.cpp` demonstrate how easy it is to use ALP to provide arbitrary fuselets that existing code bases may require, and are easily modified or extended.

This MR also includes:
 - smoke and performance tests for the new fuselets;
 - standard semiring and monoid definitions in the new `grb::monoids` and `grb::semirings` namespaces;
 - tests for those standard semirings and monoids (insofar possible);
 - a bugfix in the stdout of the spmspm unit test;
 - a bugfix for missing cstdint includes in various headers; and
 - as always, minor code style fixes.
  • Loading branch information
anyzelman authored Jan 8, 2025
1 parent 4cfb153 commit 55d74ec
Show file tree
Hide file tree
Showing 25 changed files with 3,767 additions and 88 deletions.
6 changes: 6 additions & 0 deletions include/graphblas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@
* -# #grb::Monoid, and
* -# #grb::Semiring.
*
* A list of standard operators, monoids, and semirings are provided in their
* respective name spaces:
* -# #grb::operators,
* -# #grb::monoids, and
* -# #grb::semirings.
*
* Binary operators are parametrised in two input domains and one output domain,
* \f$ D_1 \times D_2 \to D_3 \f$. The \f$ D_i \f$ are given as template
* arguments to the operator. A #grb::Monoid is composed from a binary operator
Expand Down
2 changes: 2 additions & 0 deletions include/graphblas/base/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@

#include <assert.h>

#include <cstdint> // for uintptr_t


namespace grb {

Expand Down
1 change: 1 addition & 0 deletions include/graphblas/hyperdags/hyperdags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <map>
#include <set>
#include <vector>
#include <cstdint> // uintptr_t
#include <ostream>
#include <iostream>
#include <type_traits>
Expand Down
224 changes: 141 additions & 83 deletions include/graphblas/identities.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,91 +55,130 @@ namespace grb {
/** Standard identity for numerical addition. */
template< typename D >
class zero {
static_assert( std::is_convertible< int, D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under standard addition (i.e., `zero').
*/
static constexpr D value() {
return static_cast< D >( 0 );
}

static_assert( std::is_convertible< int, D >::value,
"Cannot form identity under the requested domain" );

public:

/**
* @tparam D The domain of the value to return.
* @return The identity under standard addition (i.e., `zero').
*/
static constexpr D value() {
return static_cast< D >( 0 );
}

};

template< typename K, typename V >
class zero< std::pair< K, V > > {
public:
static constexpr std::pair< K, V > value() {
return std::make_pair( zero< K >::value(), zero< V >::value() );
}

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( zero< K >::value(), zero< V >::value() );
}

};

/** Standard identity for numerical multiplication. */
template< typename D >
class one {
static_assert( std::is_convertible< int, D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under standard multiplication (i.e., `one').
*/
static constexpr D value() {
return static_cast< D >( 1 );
}

static_assert( std::is_convertible< int, D >::value,
"Cannot form identity under the requested domain" );

public:

/**
* @tparam D The domain of the value to return.
* @return The identity under standard multiplication (i.e., `one').
*/
static constexpr D value() {
return static_cast< D >( 1 );
}

};

template< typename K, typename V >
class one< std::pair< K, V > > {
public:
static constexpr std::pair< K, V > value() {
return std::make_pair( one< K >::value(), one< V >::value() );
}

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( one< K >::value(), one< V >::value() );
}

};

/** Standard identity for the minimum operator. */
template< typename D >
class infinity {
static_assert( std::is_arithmetic< D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under the standard min operator (i.e., `infinity'),
* of type \a D.
*/
static constexpr D value() {
return std::numeric_limits< D >::has_infinity ? std::numeric_limits< D >::infinity() : std::numeric_limits< D >::max();
}
static_assert( std::is_arithmetic< D >::value,
"Cannot form identity under the requested domain" );

public:

/**
* @tparam D The domain of the value to return.
* @return The identity under the standard min operator (i.e., `infinity'),
* of type \a D.
*/
static constexpr D value() {
return std::numeric_limits< D >::has_infinity
? std::numeric_limits< D >::infinity()
: std::numeric_limits< D >::max();
}

};

template< typename K, typename V >
class infinity< std::pair< K, V > > {
public:
static constexpr std::pair< K, V > value() {
return std::make_pair( infinity< K >::value(), infinity< V >::value() );
}

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( infinity< K >::value(), infinity< V >::value() );
}

};

/** Standard identity for the maximum operator. */
template< typename D >
class negative_infinity {

static_assert( std::is_arithmetic< D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under the standard max operator, i.e.,
* `minus infinity'.
*/
static constexpr D value() {
return std::numeric_limits< D >::min() == 0 ? 0 : ( std::numeric_limits< D >::has_infinity ? -std::numeric_limits< D >::infinity() : std::numeric_limits< D >::min() );
}
public:

/**
* @tparam D The domain of the value to return.
* @return The identity under the standard max operator, i.e.,
* `minus infinity'.
*/
static constexpr D value() {
return std::numeric_limits< D >::min() == 0
? 0
: ( std::numeric_limits< D >::has_infinity
? -std::numeric_limits< D >::infinity()
: std::numeric_limits< D >::min()
);
}

};

template< typename K, typename V >
class negative_infinity< std::pair< K, V > > {
public:

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( negative_infinity< K >::value(), negative_infinity< V >::value() );
return std::make_pair( negative_infinity< K >::value(),
negative_infinity< V >::value() );
}

};

/**
Expand All @@ -149,24 +188,33 @@ namespace grb {
*/
template< typename D >
class logical_false {
static_assert( std::is_convertible< bool, D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under the standard logical OR operator, i.e.,
* \a false.
*/
static const constexpr D value() {
return static_cast< D >( false );
}

static_assert( std::is_convertible< bool, D >::value,
"Cannot form identity under the requested domain" );

public:

/**
* @tparam D The domain of the value to return.
* @return The identity under the standard logical OR operator, i.e.,
* \a false.
*/
static const constexpr D value() {
return static_cast< D >( false );
}

};

template< typename K, typename V >
class logical_false< std::pair< K, V > > {
public:
static constexpr std::pair< K, V > value() {
return std::make_pair( logical_false< K >::value(), logical_false< V >::value() );
}

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( logical_false< K >::value(),
logical_false< V >::value() );
}

};

/**
Expand All @@ -176,27 +224,37 @@ namespace grb {
*/
template< typename D >
class logical_true {
static_assert( std::is_convertible< bool, D >::value, "Cannot form identity under the requested domain" );

public:
/**
* @tparam D The domain of the value to return.
* @return The identity under the standard logical AND operator, i.e.,
* \a true.
*/
static constexpr D value() {
return static_cast< D >( true );
}

static_assert( std::is_convertible< bool, D >::value,
"Cannot form identity under the requested domain" );

public:

/**
* @tparam D The domain of the value to return.
* @return The identity under the standard logical AND operator, i.e.,
* \a true.
*/
static constexpr D value() {
return static_cast< D >( true );
}

};

template< typename K, typename V >
class logical_true< std::pair< K, V > > {
public:
static constexpr std::pair< K, V > value() {
return std::make_pair( logical_true< K >::value(), logical_true< V >::value() );
}

public:

static constexpr std::pair< K, V > value() {
return std::make_pair( logical_true< K >::value(),
logical_true< V >::value() );
}

};

} // namespace identities

} // namespace grb

#endif
Expand Down
Loading

0 comments on commit 55d74ec

Please sign in to comment.