mirror of
https://github.com/bkaradzic/bx.git
synced 2026-10-26 18:45:38 +00:00
Changed BitMaskToIndexIteratorT to clear lowest set bit instead of shifting mask down. (#473)
This commit is contained in:
@@ -14,7 +14,7 @@ namespace bx
|
||||
{
|
||||
class BitArrayViewBase;
|
||||
|
||||
/// Walks set bits of a mask, lowest first, by shifting the mask down to the next set bit.
|
||||
/// Walks set bits of a mask, lowest first, by clearing the lowest set bit.
|
||||
///
|
||||
/// @tparam MaskT Unsigned integer type of the mask.
|
||||
///
|
||||
@@ -37,8 +37,7 @@ namespace bx
|
||||
MaskT getMask() const;
|
||||
|
||||
private:
|
||||
MaskT m_mask;
|
||||
uint8_t m_idx;
|
||||
MaskT m_mask;
|
||||
};
|
||||
|
||||
/// Range-for iterator over set bits of a bit array, in index order. Dereferences to the bit
|
||||
|
||||
@@ -65,23 +65,14 @@ namespace bx
|
||||
|
||||
template<typename MaskT>
|
||||
inline BitMaskToIndexIteratorT<MaskT>::BitMaskToIndexIteratorT(MaskT _mask)
|
||||
: m_mask(0)
|
||||
, m_idx(0)
|
||||
: m_mask(_mask)
|
||||
{
|
||||
const uint8_t ntz = countTrailingZeros<MaskT>(_mask);
|
||||
m_mask = 0 == _mask ? MaskT(0) : MaskT(_mask >> ntz);
|
||||
m_idx = ntz;
|
||||
}
|
||||
|
||||
template<typename MaskT>
|
||||
inline void BitMaskToIndexIteratorT<MaskT>::next()
|
||||
{
|
||||
m_mask = MaskT(m_mask >> 1);
|
||||
m_idx += 1;
|
||||
|
||||
const uint8_t ntz = countTrailingZeros<MaskT>(m_mask);
|
||||
m_mask = 0 == m_mask ? MaskT(0) : MaskT(m_mask >> ntz);
|
||||
m_idx += ntz;
|
||||
m_mask = MaskT(m_mask & (m_mask - 1) );
|
||||
}
|
||||
|
||||
template<typename MaskT>
|
||||
@@ -93,13 +84,13 @@ namespace bx
|
||||
template<typename MaskT>
|
||||
inline uint8_t BitMaskToIndexIteratorT<MaskT>::getIndex() const
|
||||
{
|
||||
return m_idx;
|
||||
return countTrailingZeros<MaskT>(m_mask);
|
||||
}
|
||||
|
||||
template<typename MaskT>
|
||||
inline MaskT BitMaskToIndexIteratorT<MaskT>::getMask() const
|
||||
{
|
||||
return m_mask;
|
||||
return MaskT(m_mask >> getIndex() );
|
||||
}
|
||||
|
||||
inline BitArrayIterator::BitArrayIterator(const BitArrayViewBase& _view, uint32_t _idx)
|
||||
|
||||
@@ -1278,6 +1278,107 @@ TEST_CASE("BitArray-ops-bench", "[.][!benchmark]")
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MaskT>
|
||||
static uint32_t sumMaskIndices(const MaskT* _masks, uint32_t _numMasks, const uint32_t* _table)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
|
||||
for (uint32_t ii = 0; ii < _numMasks; ++ii)
|
||||
{
|
||||
for (bx::BitMaskToIndexIteratorT<MaskT> it(_masks[ii]); !it.isDone(); it.next() )
|
||||
{
|
||||
sum += _table[it.getIndex()];
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t sumSetBits(const bx::BitArrayViewBase& _bs)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
|
||||
for (const uint32_t idx : _bs)
|
||||
{
|
||||
sum += idx;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
TEST_CASE("BitArray-iterate-bench", "[.][!benchmark]")
|
||||
{
|
||||
constexpr uint32_t kNumMasks = 4096;
|
||||
constexpr uint32_t kNumBits = 64<<10;
|
||||
|
||||
bx::RngMwc rng;
|
||||
|
||||
uint32_t table[64];
|
||||
|
||||
for (uint32_t ii = 0; ii < BX_COUNTOF(table); ++ii)
|
||||
{
|
||||
table[ii] = rng.gen();
|
||||
}
|
||||
|
||||
static uint32_t streamMasks[kNumMasks];
|
||||
static uint32_t bindingMasks[kNumMasks];
|
||||
static uint64_t randomMasks[kNumMasks];
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumMasks; ++ii)
|
||||
{
|
||||
streamMasks[ii] = rng.gen() & 0xf;
|
||||
bindingMasks[ii] = rng.gen() & rng.gen() & 0xffff;
|
||||
randomMasks[ii] = (uint64_t(rng.gen() ) << 32) | rng.gen();
|
||||
}
|
||||
|
||||
BENCHMARK("mask streams 4 bits 4K")
|
||||
{
|
||||
return sumMaskIndices(streamMasks, kNumMasks, table);
|
||||
};
|
||||
|
||||
BENCHMARK("mask bindings 16 bits 4K")
|
||||
{
|
||||
return sumMaskIndices(bindingMasks, kNumMasks, table);
|
||||
};
|
||||
|
||||
BENCHMARK("mask random 64 bits 4K")
|
||||
{
|
||||
return sumMaskIndices(randomMasks, kNumMasks, table);
|
||||
};
|
||||
|
||||
alignas(64) static uint64_t bits[kNumBits/64];
|
||||
bx::MutableBitArrayView bs(bits, sizeof(bits) );
|
||||
|
||||
bs.set(0, kNumBits, true);
|
||||
|
||||
BENCHMARK("iterate dense 64K")
|
||||
{
|
||||
return sumSetBits(bs);
|
||||
};
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumBits/64; ++ii)
|
||||
{
|
||||
bits[ii] = (uint64_t(rng.gen() ) << 32) | rng.gen();
|
||||
}
|
||||
|
||||
BENCHMARK("iterate random 64K")
|
||||
{
|
||||
return sumSetBits(bs);
|
||||
};
|
||||
|
||||
bs.clear();
|
||||
|
||||
for (uint32_t ii = 0; ii < kNumBits; ii += 64)
|
||||
{
|
||||
bs.set(ii + rng.gen() % 64, true);
|
||||
}
|
||||
|
||||
BENCHMARK("iterate 1/64 64K")
|
||||
{
|
||||
return sumSetBits(bs);
|
||||
};
|
||||
}
|
||||
|
||||
static void fillRandom(bx::RngMwc& _rng, uint64_t* _bits, uint32_t _numWords)
|
||||
{
|
||||
const uint32_t mode = _rng.gen() % 4;
|
||||
|
||||
Reference in New Issue
Block a user