Skip to content

Commit 4081c37

Browse files
committed
# This is a combination of 75 commits.
# This is the 1st commit message: Issue #303: framework for reference_dense added This commit comes from a split of the original commit whose details are as follows: SHA1 ID: a7c1db0 Author: Albert-Jan Yzelman <yzelman@linux.fritz.box> 2022-01-14 15:52:26 Committer: Albert-Jan Yzelman <yzelman@linux.fritz.box> 2022-01-30 13:48:35 The reason for splitting is to separate the changes irrelevant to the branch 303 into a separate branch. The split produced 3 separate commits. This commit is number 1. This commit in particular is relevant to 303 and will remain in it. # This is the commit message #2: Issue #303: unify script argument similar to --no-reference # This is the commit message #3: Issue #303: complete implementation of Vector< reference_dense >, modulo output iteration. # This is the commit message #4: Issue #303: modified vector implementation according to option 3 in handling dense container construction. # This is the commit message #5: Issue #303: vectors now have an iterator for the user to extract data from. # This is the commit message #6: Issue #303, fixed silly oops: the difference between two iterators should be an integer # This is the commit message #7: Issue #303: containers are now uninitialized on construction. Iteration over uninitialized containers returns nothing. # This is the commit message #8: Issue #303: configure and cmake now properly do make install with reference_dense # This is the commit message #9: Issue #303: cmake infra has updated-- make dense_reference additions compatible to it # This is the commit message #10: Drafting structured matrix interface using reference_dense backend # This is the commit message #11: Issue #303: Copy test mxm.cpp to dense_mxm.cpp as a starting point # This is the commit message #12: Issue #303: Add partial first version of Matrix interface for denseref # This is the commit message #13: Issue #303: WIP: dense mxm test # This is the commit message #14: Issue #303: Add dense mxm test to CMakeLists # This is the commit message #15: Issue #303: Separate reference and reference_dense includes # This is the commit message #16: Issue #303: Fix grb include name mismatch # This is the commit message #17: Issue #303: Add src files for reference dense backend # This is the commit message #18: Issue #303: Add project related option for dense backend # This is the commit message #19: Issue #303: Remove dense_reference-related code from reference cmake # This is the commit message #20: Keeping a clean separate denseref backend when building with cmake. # This is the commit message #21: Fix cmake option name # This is the commit message #22: Use a proper data container for a denseref matrix # This is the commit message #23: Change PRIVATE to INTERFACE for denseref backend # This is the commit message #24: fix cmake config for building backend # This is the commit message #25: Add friend functions for accessing matrix dimensions and raw data # This is the commit message #26: Add first version of blas3 mxm for reference dense backend # This is the commit message #27: Add temporary code for matrix data initialization # This is the commit message #28: Complete first working dense mxm unit test # This is the commit message #29: Added structured matrix test including draft static views and references # This is the commit message #30: Convert spaces to tabs # This is the commit message #31: Make use of operators and monoid provided to mxm # This is the commit message #32: Add friend getter/setter for field 'initialized' of denseref matrix # This is the commit message #33: Revert "Add temporary code for matrix data initialization" This reverts commit 676cb4d. # This is the commit message #34: Add temporary way for allocating data of a denseref matrix # This is the commit message #35: Add functions to initialize matrix data from provided forward iterator # This is the commit message #36: Make getters const # This is the commit message #37: Exploit new features in mxm unit test New features are building a matrix from an iterator and handling of uninitialized matrices. # This is the commit message #38: added get/remove_ref type traits for StructuredMatrix types # This is the commit message #39: Temporary switch to pointers to target matrices to enable empty init. # This is the commit message #40: First draft of index mapping functions # This is the commit message #41: Cleaned up StructuredMatrix-related doxygen drafts # This is the commit message #42: Added to the spec draft # This is the commit message #43: Add alloc primitives for denseref Currently they are a copy of the same primitives for reference backend. Think whether it makes sense to group the alloc functions for these two backends. # This is the commit message #44: Handle memory allocation failure. Implement destructor. # This is the commit message #45: WIP: Add data size calculator depending on Storage scheme and structure. Also add a simple test to showcase the usage of this feature. # This is the commit message #46: Add buildMatrix for general full StructuredMatrix # This is the commit message #47: Add a check for size mismatch in buildMatrix # This is the commit message #48: Add mxm for dense Structured Matrices # This is the commit message #49: Introducing grb::get_view<> draft # This is the commit message #50: Add UpperTriangular StructuredMatrix (container and view) # This is the commit message #51: Implement polymorphic comparison of IMFs # This is the commit message #52: Add to structures a compatibility check from source structure and IMF functions This is to be used when creating a view over a source matrix using provided IMF functions. The compatibility of TargetStructure depends on the SourceStructure and provided IMF functions. This is a runtime check. # This is the commit message #53: Add constructor taking two IMFs to reference SM with general structure # This is the commit message #54: Implement gather through view with provided TargetStructure and IMFs # This is the commit message #55: Add test for gathers on StructuredMatrix using views with IMFs # This is the commit message #56: Basic VectorView definition based on grb::vector container # This is the commit message #57: Draft of diagonal (vector) view of a matrix # This is the commit message #58: Initial get_view for VectorViews # This is the commit message #59: Add a stub for Storage Mapping Functions # This is the commit message #60: Define interface for dense StructuredMatrices and scalars # This is the commit message #61: Add test showcasing eWiseApply operations on Structured Matrices # This is the commit message #62: Minor changes for dense reference vector # This is the commit message #63: Add outer product of two vectors for reference_dense backend # This is the commit message #64: Expand the gather via IMF to general view of general Storage Matrix # This is the commit message #65: Add more Structures for StructuredMatrix # This is the commit message #66: Add dot product and norm2 in blas1 for dense reference backend Also add a stub for a test showcasing their use # This is the commit message #67: WIP Constant matrix factory methods # This is the commit message #68: WIP Base classes for StructuredMatrix # This is the commit message #69: WIP Refactor StructuredMatrix using inheritance from Base classes # This is the commit message #70: Implement friend functions through base classes This avoids the need to declare friend functions inside every StructuredMatrix specialization. # This is the commit message #71: Add getter and setter for initialized field in StructuredMatrix # This is the commit message #72: Revert "WIP Constant matrix factory methods" This reverts commit 742fe9f. # This is the commit message #73: Add interface for creating constant matrices This includes Identity matrix, Zero matrix and Givens rotations # This is the commit message #74: Add test showcasing the use of Identity and Zero matrices # This is the commit message #75: Revert "WIP: Add data size calculator depending on Storage scheme and structure." This reverts commit 1f7b6c4.
1 parent 220f594 commit 4081c37

19 files changed

+1736
-383
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ project( GraphBLAS
3737
DESCRIPTION "The ultimate engine for sparse computation"
3838
LANGUAGES CXX C
3939
)
40-
set( CMAKE_CXX_STANDARD 11 )
40+
set( CMAKE_CXX_STANDARD 14 )
4141
set( CMAKE_CXX_STANDARD_REQUIRED ON )
4242

4343
# install within the build directory by default (NOT to /usr/local or the likes)

include/graphblas/base/vector.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,9 @@ namespace grb {
948948
}
949949
};
950950

951+
template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C >
952+
class VectorView { };
953+
951954
} // end namespace ``grb''
952955

953956
#endif // _H_GRB_VECTOR_BASE

include/graphblas/blas1.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#ifdef _GRB_WITH_REFERENCE
2929
#include <graphblas/reference/blas1.hpp>
3030
#endif
31-
#ifdef _GRB_WITH_DENSE
31+
#ifdef _GRB_WITH_DENSEREF
3232
#include <graphblas/denseref/blas1.hpp>
3333
#endif
3434
#ifdef _GRB_WITH_HYPERDAGS

include/graphblas/config.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#ifdef _GRB_WITH_REFERENCE
3030
#include "graphblas/reference/config.hpp"
3131
#endif
32-
#ifdef _GRB_WITH_DENSE
32+
#ifdef _GRB_WITH_DENSEREF
3333
#include "graphblas/denseref/config.hpp"
3434
#endif
3535
#ifdef _GRB_WITH_HYPERDAGS

include/graphblas/denseref/blas1.hpp

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,255 @@
2323
#ifndef _H_GRB_DENSEREF_BLAS1
2424
#define _H_GRB_DENSEREF_BLAS1
2525

26+
#include <graphblas/backends.hpp>
27+
#include <graphblas/config.hpp>
28+
#include <graphblas/rc.hpp>
29+
2630
namespace grb {
2731

32+
/**
33+
* Calculates the dot product, \f$ \alpha = (x,y) \f$, under a given additive
34+
* monoid and multiplicative operator.
35+
*
36+
* @tparam descr The descriptor to be used (descriptors::no_operation
37+
* if left unspecified).
38+
* @tparam Ring The semiring type to use.
39+
* @tparam OutputType The output type.
40+
* @tparam InputType1 The input element type of the left-hand input vector.
41+
* @tparam InputType2 The input element type of the right-hand input vector.
42+
*
43+
* @param[in,out] z The output element \f$ z + \alpha \f$.
44+
* @param[in] x The left-hand input vector.
45+
* @param[in] y The right-hand input vector.
46+
* @param[in] addMonoid The additive monoid under which the reduction of the
47+
* results of element-wise multiplications of \a x and
48+
* \a y are performed.
49+
* @param[in] anyop The multiplicative operator under which element-wise
50+
* multiplications of \a x and \a y are performed. This can
51+
* be any binary operator.
52+
*
53+
* By the definition that a dot-product operates under any additive monoid and
54+
* any binary operator, it follows that a dot-product under any semiring can be
55+
* trivially reduced to a call to this version instead.
56+
*
57+
* @return grb::MISMATCH When the dimensions of \a x and \a y do not match. All
58+
* input data containers are left untouched if this exit
59+
* code is returned; it will be as though this call was
60+
* never made.
61+
* @return grb::SUCCESS On successful completion of this call.
62+
*
63+
* \parblock
64+
* \par Performance semantics
65+
* -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where
66+
* \f$ n \f$ equals the size of the vectors \a x and \a y, and
67+
* \f$ p \f$ is the number of user processes. The constant factor
68+
* depends on the cost of evaluating the addition and multiplication
69+
* operators. A good implementation uses vectorised instructions
70+
* whenever the input domains, output domain, and the operators used
71+
* allow for this.
72+
*
73+
* -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used
74+
* by the application at the point of a call to this function.
75+
*
76+
* -# This call incurs at most
77+
* \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$
78+
* bytes of data movement.
79+
*
80+
* -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations
81+
* between two or more user processes.
82+
*
83+
* -# A call to this function does result in any system calls.
84+
* \endparblock
85+
*
86+
* \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$
87+
* memory for inter-process reduction, if the underlying communication
88+
* layer indeed requires such a buffer. This buffer may not be allocated
89+
* (nor freed) during a call to this function.
90+
*
91+
* \parblock
92+
* \par Valid descriptors
93+
* -# grb::descriptors::no_operation
94+
* -# grb::descriptors::no_casting
95+
* -# grb::descriptors::dense
96+
* \endparblock
97+
*
98+
* If the dense descriptor is set, this implementation returns grb::ILLEGAL if
99+
* it was detected that either \a x or \a y was sparse. In this case, it shall
100+
* otherwise be as though the call to this function had not occurred (no side
101+
* effects).
102+
*
103+
* \note The standard, in contrast, only specifies undefined behaviour would
104+
* occur. This implementation goes beyond the standard by actually
105+
* specifying what will happen.
106+
*/
107+
template<
108+
Descriptor descr = descriptors::no_operation,
109+
class AddMonoid, class AnyOp,
110+
typename OutputType, typename InputType1, typename InputType2,
111+
typename InputView1, typename InputView2,
112+
typename InputStorage1, typename InputStorage2,
113+
typename InputCoords1, typename InputCoords2
114+
>
115+
RC dot( OutputType &z,
116+
const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > &x,
117+
const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > &y,
118+
const AddMonoid &addMonoid = AddMonoid(),
119+
const AnyOp &anyOp = AnyOp(),
120+
const typename std::enable_if< !grb::is_object< OutputType >::value &&
121+
!grb::is_object< InputType1 >::value &&
122+
!grb::is_object< InputType2 >::value &&
123+
grb::is_monoid< AddMonoid >::value &&
124+
grb::is_operator< AnyOp >::value,
125+
void >::type * const = NULL
126+
) {
127+
(void)z;
128+
(void)x;
129+
(void)y;
130+
(void)addMonoid;
131+
(void)anyOp;
132+
// static sanity checks
133+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot",
134+
// "called with a left-hand vector value type that does not match the first "
135+
// "domain of the given multiplicative operator" );
136+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot",
137+
// "called with a right-hand vector value type that does not match the second "
138+
// "domain of the given multiplicative operator" );
139+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot",
140+
// "called with a multiplicative operator output domain that does not match "
141+
// "the first domain of the given additive operator" );
142+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot",
143+
// "called with an output vector value type that does not match the second "
144+
// "domain of the given additive operator" );
145+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot",
146+
// "called with an additive operator whose output domain does not match its "
147+
// "second input domain" );
148+
// NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot",
149+
// "called with an output vector value type that does not match the third "
150+
// "domain of the given additive operator" );
151+
152+
// dynamic sanity check
153+
// const size_t n = internal::getCoordinates( y ).size();
154+
// if( internal::getCoordinates( x ).size() != n ) {
155+
// return MISMATCH;
156+
// }
157+
158+
// // cache nnzs
159+
// const size_t nnzx = internal::getCoordinates( x ).nonzeroes();
160+
// const size_t nnzy = internal::getCoordinates( y ).nonzeroes();
161+
162+
// // catch trivial case
163+
// if( nnzx == 0 && nnzy == 0 ) {
164+
// return SUCCESS;
165+
// }
166+
167+
// // dot will be computed out-of-place here. A separate field is needed because
168+
// // of possible multi-threaded computation of the dot.
169+
// OutputType oop = addMonoid.template getIdentity< OutputType >();
170+
171+
// if descriptor says nothing about being dense...
172+
RC ret = SUCCESS;
173+
// if( !( descr & descriptors::dense ) ) {
174+
// // check if inputs are actually dense...
175+
// if( nnzx == n && nnzy == n ) {
176+
// // call dense implementation
177+
// ret = internal::dot_generic< descr | descriptors::dense >( oop, x, y, addMonoid, anyOp );
178+
// } else {
179+
// // pass to sparse implementation
180+
// ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp );
181+
// }
182+
// } else {
183+
// // descriptor says dense, but if any of the vectors are actually sparse...
184+
// if( nnzx < n || nnzy < n ) {
185+
// return ILLEGAL;
186+
// } else {
187+
// // all OK, pass to dense implementation
188+
// ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp );
189+
// }
190+
// }
191+
192+
// fold out-of-place dot product into existing input, and exit
193+
// ret = ret ? ret : foldl( z, oop, addMonoid.getOperator() );
194+
return ret;
195+
}
196+
197+
/**
198+
* Provides a generic implementation of the dot computation on semirings by
199+
* translating it into a dot computation on an additive commutative monoid
200+
* with any multiplicative operator.
201+
*
202+
* For return codes, exception behaviour, performance semantics, template
203+
* and non-template arguments, @see grb::dot.
204+
*/
205+
template<
206+
Descriptor descr = descriptors::no_operation, class Ring,
207+
typename IOType, typename InputType1, typename InputType2,
208+
typename InputView1, typename InputView2,
209+
typename InputStorage1, typename InputStorage2,
210+
Backend backend, typename Coords1, typename Coords2
211+
>
212+
RC dot( IOType &x,
213+
const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1 > &left,
214+
const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2 > &right,
215+
const Ring &ring = Ring(),
216+
const typename std::enable_if<
217+
!grb::is_object< InputType1 >::value &&
218+
!grb::is_object< InputType2 >::value &&
219+
!grb::is_object< IOType >::value &&
220+
grb::is_semiring< Ring >::value,
221+
void >::type * const = NULL
222+
) {
223+
// return grb::dot< descr >( x,
224+
return grb::dot( x,
225+
left, right,
226+
ring.getAdditiveMonoid(),
227+
ring.getMultiplicativeOperator()
228+
);
229+
}
230+
231+
/**
232+
* Provides a generic implementation of the 2-norm computation.
233+
*
234+
* Proceeds by computing a dot-product on itself and then taking the square
235+
* root of the result.
236+
*
237+
* This function is only available when the output type is floating point.
238+
*
239+
* For return codes, exception behaviour, performance semantics, template
240+
* and non-template arguments, @see grb::dot.
241+
*
242+
* @param[out] x The 2-norm of \a y. The input value of \a x will be ignored.
243+
* @param[in] y The vector to compute the norm of.
244+
* @param[in] ring The Semiring under which the 2-norm is to be computed.
245+
*
246+
* \warning This function computes \a x out-of-place. This is contrary to
247+
* standard ALP/GraphBLAS functions that are always in-place.
248+
*
249+
* \warning A \a ring is not sufficient for computing a two-norm. This
250+
* implementation assumes the standard <tt>sqrt</tt> function
251+
* must be applied on the result of a dot-product of \a y with
252+
* itself under the supplied semiring.
253+
*/
254+
template<
255+
Descriptor descr = descriptors::no_operation, class Ring,
256+
typename InputType, typename OutputType,
257+
typename InputView,
258+
typename InputStorage,
259+
Backend backend, typename Coords
260+
>
261+
RC norm2( OutputType &x,
262+
const VectorView< InputType, InputView, InputStorage, backend, Coords > &y,
263+
const Ring &ring = Ring(),
264+
const typename std::enable_if<
265+
std::is_floating_point< OutputType >::value,
266+
void >::type * const = NULL
267+
) {
268+
RC ret = grb::dot< descr >( x, y, y, ring );
269+
if( ret == SUCCESS ) {
270+
x = sqrt( x );
271+
}
272+
return ret;
273+
}
274+
28275
} // end namespace ``grb''
29276

30277
#endif // end ``_H_GRB_DENSEREF_BLAS1''

0 commit comments

Comments
 (0)