-
Notifications
You must be signed in to change notification settings - Fork 10
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
Enhancements for ArrayOf[Arrays|Sets] construction/assimilation #256
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
// Source includes | ||
#include "bufferManipulation.hpp" | ||
#include "arrayManipulation.hpp" | ||
#include "sortedArrayManipulation.hpp" | ||
#include "ArraySlice.hpp" | ||
#include "typeManipulation.hpp" | ||
#include "math.hpp" | ||
|
@@ -720,9 +721,8 @@ class ArrayOfArraysView | |
// RAJA::inclusive_scan fails on empty input range | ||
if( numSubArrays > 0 ) | ||
{ | ||
// const_cast needed until for RAJA bug. | ||
RAJA::inclusive_scan< POLICY >( const_cast< INDEX_TYPE * >( capacities ), | ||
const_cast< INDEX_TYPE * >( capacities + numSubArrays ), | ||
RAJA::inclusive_scan< POLICY >( capacities, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function should probably call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I couldn't just call it, because the result of the scan is written straight into |
||
capacities + numSubArrays, | ||
m_offsets.data() + 1 ); | ||
} | ||
|
||
|
@@ -734,6 +734,40 @@ class ArrayOfArraysView | |
}, m_values, buffers ... ); | ||
} | ||
|
||
/** | ||
* @brief Clears the array and creates a new array with the given number of sub-arrays. | ||
* @param numSubArrays The new number of arrays. | ||
* @param offsets A pointer to an array of length @p numSubArrays+1 containing the offset | ||
* of each new sub array. Offsets are precomputed by the caller. | ||
* @param buffers A variadic pack of buffers to treat similarly to m_values. | ||
*/ | ||
template< typename ... BUFFERS > | ||
void resizeFromOffsets( INDEX_TYPE const numSubArrays, | ||
INDEX_TYPE const * const offsets, | ||
BUFFERS & ... buffers ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still need to add a unit test for it. But I'd like to get the idea approved first. Usage is as follows: newAofA.resizeFromOffsets( otherAofA.size(), otherAofA.toView().getOffsets() ); We could also implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah now that I think about it (in the context of a |
||
{ | ||
LVARRAY_ASSERT( arrayManipulation::isPositive( numSubArrays ) ); | ||
LVARRAY_ASSERT_EQ( offsets[0], 0 ); | ||
LVARRAY_ASSERT( sortedArrayManipulation::isSorted( offsets, offsets + numSubArrays + 1 ) ); | ||
|
||
destroyValues( 0, m_numArrays, buffers ... ); | ||
|
||
bufferManipulation::reserve( m_sizes, m_numArrays, MemorySpace::host, numSubArrays ); | ||
std::fill_n( m_sizes.data(), numSubArrays, 0 ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is just copied from above but maybe this should use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, done |
||
|
||
INDEX_TYPE const offsetsSize = ( m_numArrays == 0 ) ? 0 : m_numArrays + 1; | ||
bufferManipulation::reserve( m_offsets, offsetsSize, MemorySpace::host, numSubArrays + 1 ); | ||
|
||
arrayManipulation::uninitializedCopy( offsets, offsets + numSubArrays + 1, m_offsets.data() ); | ||
|
||
m_numArrays = numSubArrays; | ||
INDEX_TYPE const maxOffset = m_offsets[ m_numArrays ]; | ||
typeManipulation::forEachArg( [ maxOffset ] ( auto & buffer ) | ||
{ | ||
bufferManipulation::reserve( buffer, 0, MemorySpace::host, maxOffset ); | ||
}, m_values, buffers ... ); | ||
} | ||
|
||
///@} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -121,10 +121,11 @@ class ArrayOfSets : protected ArrayOfSetsView< T, INDEX_TYPE, BUFFER_TYPE > | |
|
||
/** | ||
* @brief Steal the resources from an ArrayOfArrays and convert it to an ArrayOfSets. | ||
* @tparam POLICY a RAJA execution policy to use when sorting/removing duplicates in sub-arrays. | ||
* @param src the ArrayOfArrays to convert. | ||
* @param desc describes the type of data in the source. | ||
* TODO: Add a RAJA policy template parameter. | ||
*/ | ||
template< typename POLICY > | ||
inline | ||
void assimilate( ArrayOfArrays< T, INDEX_TYPE, BUFFER_TYPE > && src, | ||
sortedArrayManipulation::Description const desc ) | ||
|
@@ -133,38 +134,43 @@ class ArrayOfSets : protected ArrayOfSetsView< T, INDEX_TYPE, BUFFER_TYPE > | |
ParentClass::assimilate( reinterpret_cast< ParentClass && >( src ) ); | ||
|
||
INDEX_TYPE const numSets = size(); | ||
ArrayOfArraysView< T, INDEX_TYPE const, true, BUFFER_TYPE > const view = | ||
ArrayOfArraysView< T, INDEX_TYPE const, true, BUFFER_TYPE >( numSets, | ||
this->m_offsets, | ||
this->m_sizes, | ||
this->m_values ); | ||
BUFFER_TYPE< INDEX_TYPE > const sizes = this->m_sizes; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There seems to be no way to manually "resize" a single sub-array through There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks good to me. |
||
|
||
if( desc == sortedArrayManipulation::UNSORTED_NO_DUPLICATES ) | ||
{ | ||
for( INDEX_TYPE i = 0; i < numSets; ++i ) | ||
{ | ||
T * const setValues = getSetValues( i ); | ||
INDEX_TYPE const numValues = sizeOfSet( i ); | ||
std::sort( setValues, setValues + numValues ); | ||
} | ||
RAJA::forall< POLICY >( RAJA::TypedRangeSegment< INDEX_TYPE >( 0, numSets ), | ||
[view] LVARRAY_HOST_DEVICE ( INDEX_TYPE const i ) | ||
{ | ||
ArraySlice< T, 1, 0, INDEX_TYPE > const setValues = view[i]; | ||
sortedArrayManipulation::makeSorted( setValues.begin(), setValues.end() ); | ||
} ); | ||
} | ||
if( desc == sortedArrayManipulation::SORTED_WITH_DUPLICATES ) | ||
else if( desc == sortedArrayManipulation::SORTED_WITH_DUPLICATES ) | ||
{ | ||
for( INDEX_TYPE i = 0; i < numSets; ++i ) | ||
{ | ||
T * const setValues = getSetValues( i ); | ||
INDEX_TYPE const numValues = sizeOfSet( i ); | ||
|
||
INDEX_TYPE const numUniqueValues = sortedArrayManipulation::removeDuplicates( setValues, setValues + numValues ); | ||
arrayManipulation::resize( setValues, numValues, numUniqueValues ); | ||
this->m_sizes[ i ] = numUniqueValues; | ||
} | ||
RAJA::forall< POLICY >( RAJA::TypedRangeSegment< INDEX_TYPE >( 0, numSets ), | ||
[view, sizes] LVARRAY_HOST_DEVICE ( INDEX_TYPE const i ) | ||
{ | ||
ArraySlice< T, 1, 0, INDEX_TYPE > const setValues = view[i]; | ||
INDEX_TYPE const numUniqueValues = sortedArrayManipulation::removeDuplicates( setValues.begin(), setValues.end() ); | ||
arrayManipulation::resize< T >( setValues, setValues.size(), numUniqueValues ); | ||
sizes[ i ] = numUniqueValues; | ||
} ); | ||
} | ||
if( desc == sortedArrayManipulation::UNSORTED_WITH_DUPLICATES ) | ||
else if( desc == sortedArrayManipulation::UNSORTED_WITH_DUPLICATES ) | ||
{ | ||
for( INDEX_TYPE i = 0; i < numSets; ++i ) | ||
{ | ||
T * const setValues = getSetValues( i ); | ||
INDEX_TYPE const numValues = sizeOfSet( i ); | ||
|
||
INDEX_TYPE const numUniqueValues = sortedArrayManipulation::makeSortedUnique( setValues, setValues + numValues ); | ||
arrayManipulation::resize( setValues, numValues, numUniqueValues ); | ||
this->m_sizes[ i ] = numUniqueValues; | ||
} | ||
RAJA::forall< POLICY >( RAJA::TypedRangeSegment< INDEX_TYPE >( 0, numSets ), | ||
[view, sizes] LVARRAY_HOST_DEVICE ( INDEX_TYPE const i ) | ||
{ | ||
ArraySlice< T, 1, 0, INDEX_TYPE > const setValues = view[ i ]; | ||
INDEX_TYPE const numUniqueValues = sortedArrayManipulation::makeSortedUnique( setValues.begin(), setValues.end() ); | ||
arrayManipulation::resize< T >( setValues, setValues.size(), numUniqueValues ); | ||
sizes[ i ] = numUniqueValues; | ||
} ); | ||
} | ||
|
||
#ifdef ARRAY_BOUNDS_CHECK | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -429,45 +429,6 @@ class ArrayOfSetsTest : public ::testing::Test | |
} | ||
} | ||
|
||
void assimilate( IndexType const maxValue, IndexType const maxInserts, sortedArrayManipulation::Description const desc ) | ||
{ | ||
IndexType const nSets = m_array.size(); | ||
ArrayOfArraysT arrayToSteal( nSets ); | ||
|
||
for( IndexType i = 0; i < nSets; ++i ) | ||
{ | ||
IndexType const nValues = rand( 0, maxInserts ); | ||
|
||
for( IndexType j = 0; j < nValues; ++j ) | ||
{ | ||
T const value = T( rand( 0, maxValue )); | ||
bool const insertSuccess = m_ref[ i ].insert( value ).second; | ||
|
||
if( sortedArrayManipulation::isUnique( desc )) | ||
{ | ||
if( insertSuccess ) | ||
{ | ||
arrayToSteal.emplaceBack( i, value ); | ||
} | ||
} | ||
else | ||
{ | ||
arrayToSteal.emplaceBack( i, value ); | ||
} | ||
} | ||
|
||
if( sortedArrayManipulation::isSorted( desc )) | ||
{ | ||
T * const values = arrayToSteal[ i ]; | ||
std::sort( values, values + arrayToSteal.sizeOfArray( i )); | ||
} | ||
} | ||
|
||
m_array.assimilate( std::move( arrayToSteal ), desc ); | ||
|
||
COMPARE_TO_REFERENCE | ||
} | ||
|
||
protected: | ||
|
||
template< typename CONTAINER > | ||
|
@@ -691,30 +652,6 @@ TYPED_TEST( ArrayOfSetsTest, shallowCopy ) | |
this->shallowCopy(); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsTest, assimilateSortedUnique ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::SORTED_UNIQUE ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsTest, assimilateUnsortedNoDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::UNSORTED_NO_DUPLICATES ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsTest, assimilateSortedWithDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::SORTED_WITH_DUPLICATES ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsTest, assimilateUnsortedWithDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::UNSORTED_WITH_DUPLICATES ); | ||
} | ||
|
||
// This is testing capabilities of the ArrayOfArrays class, however it needs to first populate | ||
// the ArrayOfSets so it involves less code duplication to put it here. | ||
TYPED_TEST( ArrayOfSetsTest, ArrayOfArraysStealFrom ) | ||
|
@@ -754,6 +691,7 @@ class ArrayOfSetsViewTest : public ArrayOfSetsTest< typename ARRAY_OF_SETS_POLIC | |
using typename ParentClass::IndexType; | ||
using typename ParentClass::ViewType; | ||
using typename ParentClass::ViewTypeConst; | ||
using typename ParentClass::ArrayOfArraysT; | ||
|
||
template< typename U > | ||
using Array1D = typename ToArray< U, ARRAY_OF_SETS >::OneD; | ||
|
@@ -890,6 +828,47 @@ class ArrayOfSetsViewTest : public ArrayOfSetsTest< typename ARRAY_OF_SETS_POLIC | |
COMPARE_TO_REFERENCE | ||
} | ||
|
||
// This is not a View test, but it needs a POLICY type argument, so it's placed here for convenience | ||
void assimilate( IndexType const maxValue, IndexType const maxInserts, sortedArrayManipulation::Description const desc ) | ||
Comment on lines
+831
to
+832
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lmk if you'd like a separate test sub-class to contain these assimilation tests (I moved them from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope that sounds just fine. I've done similar things elsewhere. |
||
{ | ||
IndexType const nSets = m_array.size(); | ||
ArrayOfArraysT arrayToSteal( nSets ); | ||
|
||
for( IndexType i = 0; i < nSets; ++i ) | ||
{ | ||
IndexType const nValues = rand( 0, maxInserts ); | ||
|
||
for( IndexType j = 0; j < nValues; ++j ) | ||
{ | ||
T const value = T( rand( 0, maxValue )); | ||
bool const insertSuccess = m_ref[ i ].insert( value ).second; | ||
|
||
if( sortedArrayManipulation::isUnique( desc )) | ||
{ | ||
if( insertSuccess ) | ||
{ | ||
arrayToSteal.emplaceBack( i, value ); | ||
} | ||
} | ||
else | ||
{ | ||
arrayToSteal.emplaceBack( i, value ); | ||
} | ||
} | ||
|
||
if( sortedArrayManipulation::isSorted( desc )) | ||
{ | ||
T * const values = arrayToSteal[ i ]; | ||
std::sort( values, values + arrayToSteal.sizeOfArray( i )); | ||
} | ||
} | ||
|
||
m_array.template assimilate< POLICY >( std::move( arrayToSteal ), desc ); | ||
|
||
m_array.move( MemorySpace::host ); | ||
COMPARE_TO_REFERENCE | ||
} | ||
|
||
protected: | ||
|
||
Array1D< Array1D< T > > createValues( bool const insert, bool const sortedUnique ) | ||
|
@@ -1012,6 +991,30 @@ TYPED_TEST( ArrayOfSetsViewTest, removeMultiple ) | |
} | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsViewTest, assimilateSortedUnique ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::SORTED_UNIQUE ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsViewTest, assimilateUnsortedNoDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::UNSORTED_NO_DUPLICATES ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsViewTest, assimilateSortedWithDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::SORTED_WITH_DUPLICATES ); | ||
} | ||
|
||
TYPED_TEST( ArrayOfSetsViewTest, assimilateUnsortedWithDuplicates ) | ||
{ | ||
this->resize( 50 ); | ||
this->assimilate( DEFAULT_MAX_INSERTS, DEFAULT_MAX_VALUE, sortedArrayManipulation::UNSORTED_WITH_DUPLICATES ); | ||
} | ||
|
||
} // namespace testing | ||
} // namespace LvArray | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Casts seem no longer needed with current version of RAJA we're using