Skip to content

Commit

Permalink
Resolve issue #105. Remove unused "convenience" constructors for Dens…
Browse files Browse the repository at this point in the history
…eSkOp. Breaking API change that removes fill_dense(dist, n_rows, n_cols, ro_s, co_s, buff, seed) --- which returned a tuple of Layout and RNGState --- and replaces it with fill_dense(layout, dist, n_rows, n_cols, ro_s, co_s, buff, seed) --- which returns an RNGState.
  • Loading branch information
rileyjmurray committed Aug 2, 2024
1 parent d731290 commit d7b9970
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 244 deletions.
248 changes: 73 additions & 175 deletions RandBLAS/dense_skops.hh

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions RandBLAS/random_gen.hh
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ struct uneg11
*
* @tparam RNG a random123 CBRNG type
*
* @param[in] a random123 CBRNG instance used to generate the sequence
* @param[in] the CBRNG counter
* @param[in] the CBRNG key
* @param[in] rng: a random123 CBRNG instance used to generate the sequence
* @param[in] c: CBRNG counter
* @param[in] k: CBRNG key
*
* @returns a std::array<N,T> where N is the CBRNG's ctr_type::static_size
* and T is deduced from the RNG's counter element type : float
Expand Down
18 changes: 4 additions & 14 deletions RandBLAS/skge.hh
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,8 @@ void lskge3(
){
auto [rows_submat_S, cols_submat_S] = dims_before_op(d, m, opS);
if (!S.buff) {
// We'll make a shallow copy of the sketching operator, take responsibility for filling the memory
// of that sketching operator, and then call LSKGE3 with that new object.
T *work = new T[rows_submat_S * cols_submat_S];
fill_dense(S.layout, S.dist, rows_submat_S, cols_submat_S, ro_s, co_s, work, S.seed_state);
DenseDist D_{rows_submat_S, cols_submat_S, DenseDistName::BlackBox, MajorAxis::Undefined};
DenseSkOp S_(D_, S.seed_state, work, S.layout);
lskge3(layout, opS, opA, d, n, m, alpha, S_, 0, 0, A, lda, beta, B, ldb);
delete [] work;
auto submat_S = submatrix_as_blackbox(S, rows_submat_S, cols_submat_S, ro_s, co_s);
lskge3(layout, opS, opA, d, n, m, alpha, submat_S, 0, 0, A, lda, beta, B, ldb);
return;
}
randblas_require( S.dist.n_rows >= rows_submat_S + ro_s );
Expand Down Expand Up @@ -345,12 +339,8 @@ void rskge3(
if (!S.buff) {
// We'll make a shallow copy of the sketching operator, take responsibility for filling the memory
// of that sketching operator, and then call RSKGE3 with that new object.
T *work = new T[rows_submat_S * cols_submat_S];
fill_dense(S.layout, S.dist, rows_submat_S, cols_submat_S, ro_s, co_s, work, S.seed_state);
DenseDist D_{rows_submat_S, cols_submat_S, DenseDistName::BlackBox, MajorAxis::Undefined};
DenseSkOp S_(D_, S.seed_state, work, S.layout);
rskge3(layout, opA, opS, m, d, n, alpha, A, lda, S_, 0, 0, beta, B, ldb);
delete [] work;
auto submat_S = submatrix_as_blackbox(S, rows_submat_S, cols_submat_S, ro_s, co_s);
rskge3(layout, opA, opS, m, d, n, alpha, A, lda, submat_S, 0, 0, beta, B, ldb);
return;
}
randblas_require( S.dist.n_rows >= rows_submat_S + ro_s );
Expand Down
16 changes: 4 additions & 12 deletions RandBLAS/sparse_data/sksp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,8 @@ void lsksp3(
// B = op(submat(S)) @ op(submat(A))
auto [rows_submat_S, cols_submat_S] = dims_before_op(d, m, opS);
if (!S.buff) {
T *buff = new T[rows_submat_S * cols_submat_S];
fill_dense(S.dist, rows_submat_S, cols_submat_S, ro_s, co_s, buff, S.seed_state);
DenseDist D{rows_submat_S, cols_submat_S, DenseDistName::BlackBox, S.dist.major_axis};
DenseSkOp S_(D, S.seed_state, buff);
lsksp3(layout, opS, opA, d, n, m, alpha, S_, 0, 0, A, ro_a, co_a, beta, B, ldb);
delete [] buff;
auto submat_S = submatrix_as_blackbox(S, rows_submat_S, cols_submat_S, ro_s, co_s);
lsksp3(layout, opS, opA, d, n, m, alpha, submat_S, 0, 0, A, ro_a, co_a, beta, B, ldb);
return;
}

Expand Down Expand Up @@ -324,12 +320,8 @@ void rsksp3(
) {
auto [rows_submat_S, cols_submat_S] = dims_before_op(n, d, opS);
if (!S.buff) {
T *buff = new T[rows_submat_S * cols_submat_S];
fill_dense(S.dist, rows_submat_S, cols_submat_S, ro_s, co_s, buff, S.seed_state);
DenseDist D{rows_submat_S, cols_submat_S, DenseDistName::BlackBox, S.dist.major_axis};
DenseSkOp S_(D, S.seed_state, buff);
rsksp3(layout, opA, opS, m, d, n, alpha, A, ro_a, co_a, S_, 0, 0, beta, B, ldb);
delete [] buff;
auto submat_S = submatrix_as_blackbox(S, rows_submat_S, cols_submat_S, ro_s, co_s);
rsksp3(layout, opA, opS, m, d, n, alpha, A, ro_a, co_a, submat_S, 0, 0, beta, B, ldb);
return;
}
auto [rows_submat_A, cols_submat_A] = dims_before_op(m, n, opA);
Expand Down
5 changes: 0 additions & 5 deletions RandBLAS/sparse_skops.hh
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,6 @@ struct SparseSkOp {
///
/// @param[in] S
/// SparseSkOp object.
///
/// @return
/// An RNGState object. This is the state that should be used the next
/// time the program needs to generate random numbers for a randomized
/// algorithm.
///
template <typename T, typename RNG, SignedInteger sint_t>
void fill_sparse(
Expand Down
12 changes: 7 additions & 5 deletions rtd/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@
RandBLAS: sketching for randomized numerical linear algebra
===========================================================

RandBLAS is a C++ library for dimension reduction via random linear transformations.
These random linear transformations are called *sketching operators*.
The act of applying a sketching operator -- that is, the act of *sketching* -- is of fundamental importance to randomized numerical linear algebra.
RandBLAS is a C++ library for randomized linear dimension reduction -- an operation commonly known as *sketching*.
We built RandBLAS to make it easier to write, debug, and deploy high-performance implementations of sketching-based algorithms.

RandBLAS is efficient, flexible, and reliable.
It uses CPU-based OpenMP acceleration to apply its sketching operators to dense or sparse data matrices stored in main memory.

All sketches produced by RandBLAS are dense.
As such, dense data matrices can be sketched with dense or sparse operators, while sparse data matrices can only be sketched with dense operators.
RandBLAS can be used in distributed environments through its ability to (reproducibly) compute products with *submatrices* of sketching operators.
If you have RandBLAS and an LAPACK-like library at your disposal, you can implement
a huge range of shared-memory randomized algorithms for matrix computations.
RandBLAS can be used in distributed environments through its ability to compute products with *submatrices* of sketching operators,
without ever realizing the entire sketching operator in memory.

Learn more by reading our `tutorial <tutorial/index.html>`_ or our `API reference <api_reference/index.html>`_.
If we've piqued your interest, try RandBLAS yourself!
Expand Down
30 changes: 8 additions & 22 deletions rtd/source/tutorial/sampling_skops.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ Formal API docs for the recommended constructors can be found :ref:`here <densed
Constructing your :math:`N^{\text{th}}` sketching operator, for :math:`N > 1`
==============================================================================

Suppose you have an application that requires two independent dense sketching operators,
:math:`\texttt{S1}` and :math:`\texttt{S2}`, each of size :math:`10000 \times 50`.
How should you get your hands on these objects?
Suppose you have an application that requires two statistically independent dense
sketching operators, :math:`\texttt{S1}` and :math:`\texttt{S2}`, each of size
:math:`10000 \times 50`. How should you get your hands on these objects?

.. warning::
If you try to construct those sketching operators as follows ...
Expand All @@ -88,33 +88,19 @@ How should you get your hands on these objects?
*then your results would be invalid! Far from being independent,* :math:`\texttt{S1}`
*and* :math:`\texttt{S2}` *would be equal from a mathematical perspective.*

One correct approach is to first
fill the entries of :math:`\texttt{S1}`, and then call
the constructor for :math:`\texttt{S2}` using :math:`\texttt{S1.next_state}`
as its RNGState argument:
One correct approach is to then call the constructor for :math:`\texttt{S2}`
using :math:`\texttt{S1.next_state}` as its RNGState argument:

.. code:: c++

RandBLAS::RNGState my_state();
RandBLAS::DenseDist my_dist(10000, 50);
RandBLAS::DenseSkOp<double> S1(my_dist, my_state);
// ^ Defines S1 from a mathematical perspective, but performs no work.
// RandBLAS hasn't made any calls to a CBRNG.
RandBLAS::fill_dense(S1);
// ^ RandBLAS uses a CBRNG to sample each entry of S1,
// then sets S1.next_state.
// ^ Defines S1 from a mathematical perspective. Computes S1.next_state,
// but otherwise performs no work.
RandBLAS::DenseSkOp<double> S2(my_dist, S1.next_state);

The shortcoming of this approach is that it requires explicitly filling
:math:`\texttt{S1}` just to define :math:`\texttt{S2}` in a mathematical sense.
There are two alternative approaches you can use if this shortcoming is
significant in your application.

*Alternative 1*. Define one larger sketching operator
(here, a :math:`10000\times 100` sketching operator) and operate with
appropriate submatrices of that larger operator when needed.

*Alternative 2*. Declare two RNGState objects from the beginning using
Another valid approach is to declare two RNGState objects from the beginning using
different keys, as in the following code:

.. code:: c++
Expand Down
8 changes: 4 additions & 4 deletions test/test_datastructures/test_denseskop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class TestDenseMoments : public ::testing::Test {
// Construct the sketching operator
RandBLAS::DenseDist D(n_rows, n_cols, dn);
auto state = RandBLAS::RNGState(key);
auto [layout, next_state] = RandBLAS::fill_dense(D, A.data(), state);
auto next_state = RandBLAS::fill_dense(D, A.data(), state);

// Compute the entrywise empirical mean and standard deviation.
T mean = std::accumulate(A.data(), A.data() + size, 0.0) /size;
Expand Down Expand Up @@ -433,7 +433,7 @@ class TestStateUpdate : public ::testing::Test
RandBLAS::DenseDist D(n_rows, n_cols, dn);

auto state = RandBLAS::RNGState(key);
auto [layout, next_state] = RandBLAS::fill_dense(D, A.data(), state);
auto next_state = RandBLAS::fill_dense(D, A.data(), state);
RandBLAS::fill_dense(D, B.data(), next_state);

ASSERT_TRUE(!(A == B));
Expand Down Expand Up @@ -476,7 +476,7 @@ class TestStateUpdate : public ::testing::Test
auto state1 = RandBLAS::RNGState(key);

// Concatenates two matrices generated from state and next_state
auto [layout, next_state] = RandBLAS::fill_dense(D1, A.data(), state);
auto next_state = RandBLAS::fill_dense(D1, A.data(), state);
RandBLAS::fill_dense(D3, A.data() + (int64_t) (D1.n_rows * D1.n_cols), next_state);

RandBLAS::fill_dense(D2, B.data(), state1);
Expand Down Expand Up @@ -504,7 +504,7 @@ class TestStateUpdate : public ::testing::Test

typename RNG::ctr_type c_ref = state_copy.counter;

auto [layout, final_state] = RandBLAS::fill_dense(D, buff, state);
auto final_state = RandBLAS::fill_dense(D, buff, state);
auto c = final_state.counter;
int c_len = c.size();

Expand Down
2 changes: 1 addition & 1 deletion test/test_datastructures/test_spmats/common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void iid_sparsify_random_dense(
) {
auto spar = new T[n_rows * n_cols];
auto dist = RandBLAS::DenseDist(n_rows, n_cols, RandBLAS::DenseDistName::Uniform);
auto [unused, next_state] = RandBLAS::fill_dense(dist, spar, state);
auto next_state = RandBLAS::fill_dense(dist, spar, state);

auto temp = new T[n_rows * n_cols];
auto D_mat = RandBLAS::DenseDist(n_rows, n_cols, RandBLAS::DenseDistName::Uniform);
Expand Down
4 changes: 2 additions & 2 deletions test/test_matmul_cores/linop_common.hh
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ template <typename T, typename RNG=r123::Philox4x32>
auto random_matrix(int64_t m, int64_t n, RNGState<RNG> s) {
std::vector<T> A(m * n);
DenseDist DA(m, n);
auto [layout, next_state] = RandBLAS::fill_dense(DA, A.data(), s);
std::tuple<std::vector<T>, Layout, RNGState<RNG>> t{A, layout, next_state};
auto next_state = RandBLAS::fill_dense(DA, A.data(), s);
std::tuple<std::vector<T>, Layout, RNGState<RNG>> t{A, RandBLAS::dist_to_layout(DA), next_state};
return t;
}

Expand Down
2 changes: 1 addition & 1 deletion test/test_matmul_wrappers/test_sketch_symmetric.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void random_symmetric_mat(int64_t n, T* A, int64_t lda, STATE s) {
// This function can be interpreted as first generating a random lda-by-lda symmetric matrix
// whose entries in the upper triangle are iid, then symmetrizing that matrix, then
// zeroing out all entries outside the leading principal submatrix of order n.
RandBLAS::fill_dense({lda, lda}, n, n, 0, 0, A, s);
RandBLAS::fill_dense(Layout::ColMajor, {lda, lda}, n, n, 0, 0, A, s);
RandBLAS::util::symmetrize(Layout::ColMajor, Uplo::Upper, A, n, lda);
return;
}
Expand Down

0 comments on commit d7b9970

Please sign in to comment.