[mathicgb] 96/393: Made some changes to MonomialMap to prepare for using a single concurrent hashtable instead of per-thread hash tables. This (temporarily) has made it fixed-size. Performance is, unexpectedly, better by 1% single-core. This happened when forcing the internal table pointer and mask onto the stack of clients (via a handle). I'm not sure if the cause of the better performance is due to better compiler information (const-on-stack is easy to prove things about for compilers) or just that things are done slightly differently which happens to randomly emit better code.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:39 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.
commit 6c3cf91bdcc9ab2a584e0671de809d26ef7cde02
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Sat Nov 3 16:38:36 2012 +0100
Made some changes to MonomialMap to prepare for using a single concurrent hashtable instead of per-thread hash tables. This (temporarily) has made it fixed-size. Performance is, unexpectedly, better by 1% single-core. This happened when forcing the internal table pointer and mask onto the stack of clients (via a handle). I'm not sure if the cause of the better performance is due to better compiler information (const-on-stack is easy to prove things about for compilers) or just that th [...]
---
src/mathicgb/F4MatrixBuilder.cpp | 56 +++-
src/mathicgb/F4MatrixBuilder.hpp | 18 +-
src/mathicgb/MonomialMap.hpp | 591 ++++++++++++++++++++++---------------
src/mathicgb/PolyRing.hpp | 3 +-
src/mathicgb/QuadMatrixBuilder.hpp | 6 +
5 files changed, 431 insertions(+), 243 deletions(-)
diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index 99315f3..36e7382 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -5,7 +5,7 @@
#include <omp.h>
#endif
-MATHICGB_INLINE QuadMatrixBuilder::LeftRightColIndex
+MATHICGB_NO_INLINE QuadMatrixBuilder::LeftRightColIndex
F4MatrixBuilder::findOrCreateColumn
(
const const_monomial monoA,
@@ -20,7 +20,23 @@ MATHICGB_INLINE QuadMatrixBuilder::LeftRightColIndex
return createColumn(builder, monoA, monoB);
}
-MATHICGB_INLINE const std::pair<
+MATHICGB_INLINE QuadMatrixBuilder::LeftRightColIndex
+ F4MatrixBuilder::findOrCreateColumn
+(
+ const const_monomial monoA,
+ const const_monomial monoB,
+ const ColSnapshotReader& colMap,
+ QuadMatrixBuilder& builder
+) {
+ MATHICGB_ASSERT(!monoA.isNull());
+ MATHICGB_ASSERT(!monoB.isNull());
+ const auto col = colMap.findProduct(monoA, monoB);
+ if (col == 0)
+ return createColumn(builder, monoA, monoB);
+ return *col;
+}
+
+MATHICGB_NO_INLINE const std::pair<
QuadMatrixBuilder::LeftRightColIndex,
QuadMatrixBuilder::LeftRightColIndex
> F4MatrixBuilder::findOrCreateTwoColumns
@@ -49,6 +65,27 @@ MATHICGB_INLINE const std::pair<
return colPair;
}
+MATHICGB_INLINE const std::pair<
+ QuadMatrixBuilder::LeftRightColIndex,
+ QuadMatrixBuilder::LeftRightColIndex
+> F4MatrixBuilder::findOrCreateTwoColumns
+(
+ const const_monomial monoA1,
+ const const_monomial monoA2,
+ const const_monomial monoB,
+ const ColSnapshotReader& colMap,
+ QuadMatrixBuilder& builder
+) {
+ MATHICGB_ASSERT(!monoA1.isNull());
+ MATHICGB_ASSERT(!monoA2.isNull());
+ MATHICGB_ASSERT(!monoB.isNull());
+ MATHICGB_ASSERT(!ring().monomialEQ(monoA1, monoA2));
+ auto colPair = colMap.findTwoProducts(monoA1, monoA2, monoB);
+ if (colPair.first == 0 || colPair.second == 0)
+ return findOrCreateTwoColumns(monoA1, monoA2, monoB, builder);
+ return std::make_pair(*colPair.first, *colPair.second);
+}
+
F4MatrixBuilder::F4MatrixBuilder(
const PolyBasis& basis,
const int threadCount,
@@ -334,9 +371,10 @@ void F4MatrixBuilder::appendRowBottom(
// todo: eliminate the code-duplication between here and appendRowTop.
MATHICGB_ASSERT(!multiple.isNull());
MATHICGB_ASSERT(&builder != 0);
+ const ColSnapshotReader colMap(builder.columnToIndexMap());
for (auto it = begin; it != end; ++it) {
- const auto col = findOrCreateColumn(it.getMonomial(), multiple, builder);
+ const auto col = findOrCreateColumn(it.getMonomial(), multiple, colMap, builder);
const auto origScalar = it.getCoefficient();
MATHICGB_ASSERT(origScalar != 0);
const auto possiblyNegated =
@@ -356,10 +394,12 @@ void F4MatrixBuilder::appendRowTop(
MATHICGB_ASSERT(&poly != 0);
MATHICGB_ASSERT(&builder != 0);
+ QuadMatrixBuilder::ColSnapshotReader colMap(builder.columnToIndexMap());
+
auto it = poly.begin();
const auto end = poly.end();
if ((std::distance(it, end) % 2) == 1) {
- const auto col = findOrCreateColumn(it.getMonomial(), multiple, builder);
+ const auto col = findOrCreateColumn(it.getMonomial(), multiple, colMap, builder);
MATHICGB_ASSERT(it.getCoefficient() < std::numeric_limits<Scalar>::max());
MATHICGB_ASSERT(it.getCoefficient());
builder.appendEntryTop(col, static_cast<Scalar>(it.getCoefficient()));
@@ -380,7 +420,7 @@ void F4MatrixBuilder::appendRowTop(
++it;
const auto colPair =
- findOrCreateTwoColumns(mono1, mono2, multiple, builder);
+ findOrCreateTwoColumns(mono1, mono2, multiple, colMap, builder);
builder.appendEntryTop(colPair.first, scalar1);
builder.appendEntryTop(colPair.second, scalar2);
}
@@ -414,6 +454,8 @@ void F4MatrixBuilder::appendRowBottom(
++itA;
++itB;
+ const ColSnapshotReader colMap(builder.columnToIndexMap());
+
const const_monomial mulA = task.multiply;
const const_monomial mulB = task.sPairMultiply;
while (true) {
@@ -431,8 +473,8 @@ void F4MatrixBuilder::appendRowBottom(
coefficient coeff = 0;
LeftRightColIndex col;
- const auto colA = findOrCreateColumn(itA.getMonomial(), mulA, builder);
- const auto colB = findOrCreateColumn(itB.getMonomial(), mulB, builder);
+ const auto colA = findOrCreateColumn(itA.getMonomial(), mulA, colMap, builder);
+ const auto colB = findOrCreateColumn(itB.getMonomial(), mulB, colMap, builder);
const auto cmp = ring().monomialCompare
(builder.monomialOfCol(colA), builder.monomialOfCol(colB));
if (cmp != LT) {
diff --git a/src/mathicgb/F4MatrixBuilder.hpp b/src/mathicgb/F4MatrixBuilder.hpp
index 48b3220..8138cc6 100755
--- a/src/mathicgb/F4MatrixBuilder.hpp
+++ b/src/mathicgb/F4MatrixBuilder.hpp
@@ -66,6 +66,8 @@ public:
const PolyRing& ring() const {return mBuilder.ring();}
private:
+ typedef const QuadMatrixBuilder::ColSnapshotReader ColSnapshotReader;
+
/** Creates a column with monomial label x and schedules a new row to
reduce that column if possible. Here x is monoA if monoB is
null and otherwise x is the product of monoA and monoB. */
@@ -97,18 +99,30 @@ private:
QuadMatrixBuilder& builder
);
- MATHICGB_INLINE LeftRightColIndex findOrCreateColumn
+ MATHICGB_NO_INLINE LeftRightColIndex findOrCreateColumn
(const_monomial monoA, const_monomial monoB, QuadMatrixBuilder& builder);
+ MATHICGB_INLINE LeftRightColIndex findOrCreateColumn(
+ const_monomial monoA,
+ const_monomial monoB,
+ const ColSnapshotReader& colMap,
+ QuadMatrixBuilder& builder);
+ MATHICGB_NO_INLINE const std::pair<LeftRightColIndex, LeftRightColIndex>
+ findOrCreateTwoColumns(
+ const const_monomial monoA1,
+ const const_monomial monoA2,
+ const const_monomial monoB,
+ QuadMatrixBuilder& builder
+ );
MATHICGB_INLINE const std::pair<LeftRightColIndex, LeftRightColIndex>
findOrCreateTwoColumns(
const const_monomial monoA1,
const const_monomial monoA2,
const const_monomial monoB,
+ const ColSnapshotReader& colMap,
QuadMatrixBuilder& builder
);
-
const int mThreadCount;
monomial mTmp;
std::vector<RowTask> mTodo;
diff --git a/src/mathicgb/MonomialMap.hpp b/src/mathicgb/MonomialMap.hpp
index f3c399e..037b5cc 100755
--- a/src/mathicgb/MonomialMap.hpp
+++ b/src/mathicgb/MonomialMap.hpp
@@ -2,40 +2,225 @@
#define MATHICGB_MONOMIAL_MAP_GUARD
#include "PolyRing.hpp"
-#include <limits>
-
-#if defined(MATHICGB_USE_STD_HASH) && defined(MATHICGB_USE_CUSTOM_HASH)
-#error Only select one kind of hash table
-#endif
-
-// set default hash table type if nothing has been specified
-#if !defined(MATHICGB_USE_STD_HASH) && !defined(MATHICGB_USE_CUSTOM_HASH)
-#define MATHICGB_USE_CUSTOM_HASH
-#endif
-
-#ifdef MATHICGB_USE_CUSTOM_HASH
#include <memtailor.h>
+#include <limits>
#include <vector>
#include <algorithm>
-#elif defined(MATHICGB_USE_STD_HASH)
-#include <unordered_map>
-#else
-#include <map>
-#endif
-/** A mapping from monomials to MapToType. The interface is the same as
- for STL maps. The interface is not complete. Add methods you need when
- you need it.
-*/
+/// A mapping from monomials to MapToType. The interface is the same as
+/// for STL maps. The interface is not complete. Add methods you need when
+/// you need it.
template<class MapToType>
class MonomialMap;
+template<class MTT>
+class FixedSizeMonomialMap {
+public:
+ typedef MTT mapped_type;
+ typedef std::pair<const_monomial, mapped_type> value_type;
+
+private:
+ struct Node {
+ Node* next;
+ mapped_type value;
+ exponent mono[1];
+ };
+
+ static HashValue computeHashMask(const size_t requestedBucketCount) {
+ // round request up to nearest power of 2.
+ size_t pow2 = 1;
+ while (pow2 < requestedBucketCount && 2 * pow2 != 0)
+ pow2 *= 2;
+ MATHICGB_ASSERT(pow2 > 0 && (pow2 & (pow2 - 1)) == 0); // power of two
+
+ // If casting to a hash value overflows, then we get the maximum
+ // possible number of buckets based on the range of the hash
+ // value type. Only unsigned overflow is defined, so we need
+ // to assert that the hash type is unsigned.
+ static_assert(!std::numeric_limits<HashValue>::is_signed, "");
+ const auto hashToIndexMask = static_cast<HashValue>(pow2 - 1);
+ MATHICGB_ASSERT(pow2 == hashMaskToBucketCount(hashToIndexMask));
+ return hashToIndexMask;
+ }
+
+ static size_t hashMaskToBucketCount(const HashValue mask) {
+ const auto count = static_cast<size_t>(mask) + 1u; // should be power of 2
+ MATHICGB_ASSERT(count > 0 && (count & (count - 1)) == 0);
+ return count;
+ }
+
+ static size_t sizeofNode(const PolyRing& ring) {
+ return sizeof(Node) - sizeof(exponent) + ring.maxMonomialByteSize();
+ }
+
+public:
+ size_t bucketCount() const {
+ return hashMaskToBucketCount(mHashToIndexMask);
+ }
+
+ FixedSizeMonomialMap(
+ const size_t requestedBucketCount,
+ const PolyRing& ring
+ ):
+ mHashToIndexMask(computeHashMask(requestedBucketCount)),
+ mBuckets(new Node*[hashMaskToBucketCount(mHashToIndexMask)]),
+ mRing(ring),
+ mNodeAlloc(sizeofNode(ring)),
+ mEntryCount(0)
+ {
+ std::fill_n(mBuckets, bucketCount(), static_cast<Node*>(0));
+ }
+
+ ~FixedSizeMonomialMap() {
+ delete[] mBuckets;
+ }
+
+ FixedSizeMonomialMap(
+ const size_t requestedBucketCount,
+ const FixedSizeMonomialMap& map
+ ):
+ mHashToIndexMask(computeHashMask(requestedBucketCount)),
+ mBuckets(new Node*[hashMaskToBucketCount(mHashToIndexMask)]),
+ mRing(map.ring()),
+ mNodeAlloc(sizeofNode(map.ring())),
+ mEntryCount(0)
+ {
+ for (size_t bucket = 0; bucket < map.bucketCount(); ++bucket)
+ for (Node* node = map.mBuckets[bucket]; node != 0; node = node->next)
+ insert(std::make_pair(node->mono, node->value));
+ /*
+ todo: use this code once we have a move constructor for mNodeAlloc.
+ // Move nodes from current table into new table
+ decltype(mBuckets) newTable(newTableSize);
+ HashValue newHashToIndexMask = static_cast<HashValue>(newTableSize - 1);
+ const auto tableEnd = mBuckets.end();
+ for (auto tableIt = mBuckets.begin(); tableIt != tableEnd; ++tableIt) {
+ Node* node = *tableIt;
+ while (node != 0) {
+ const size_t index =
+ mRing.monomialHashValue(node->mono) & newHashToIndexMask;
+ MATHICGB_ASSERT(index < newTable.size());
+ Node* const next = node->next;
+ node->next = newTable[index];
+ newTable[index] = node;
+ node = next;
+ }
+ }
+
+ // Move newly calculated table into place
+ mBucketsSize = newTableSize;
+ mBuckets = std::move(newTable);
+ mHashToIndexMask = newHashToIndexMask;
+ mGrowWhenThisManyEntries = newGrowWhenThisManyEntries;
+
+ MATHICGB_ASSERT(mBucketsSize < mGrowWhenThisManyEntries);
+ */
+ }
+
+ const PolyRing& ring() const {return mRing;}
+ size_t size() const {return mEntryCount;}
+
+ const mapped_type* find(const const_monomial mono) const {
+ const HashValue monoHash = mRing.monomialHashValue(mono);
+ const Node* node = bucketAtIndex(hashToIndex(monoHash));
+ for (; node != 0; node = node->next) {
+ // To my surprise, it seems to be faster to comment out this branch.
+ // I guess the hash table has too few collisions to make it worth it.
+ //if (monoHash != mRing.monomialHashValue(node->mono))
+ // continue;
+ if (mRing.monomialEqualHintTrue(mono, node->mono))
+ return &node->value;
+ }
+ return 0;
+ }
+
+ MATHICGB_INLINE const mapped_type* findProduct(
+ const const_monomial a,
+ const const_monomial b
+ ) const {
+ const HashValue abHash = mRing.monomialHashOfProduct(a, b);
+ const Node* node = bucketAtIndex(hashToIndex(abHash));
+ for (; node != 0; node = node->next) {
+ // To my surprise, it seems to be faster to comment out this branch.
+ // I guess the hash table has too few collisions to make it worth it.
+ //if (abHash != mRing.monomialHashValue(node->mono))
+ // continue;
+ if (mRing.monomialIsProductOfHintTrue(a, b, node->mono))
+ return &node->value;
+ }
+ return 0;
+ }
+
+ /// As findProduct but looks for a1*b and a2*b at one time.
+ MATHICGB_INLINE
+ std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
+ const const_monomial a1,
+ const const_monomial a2,
+ const const_monomial b
+ ) const {
+ const HashValue a1bHash = mRing.monomialHashOfProduct(a1, b);
+ const HashValue a2bHash = mRing.monomialHashOfProduct(a2, b);
+ const Node* const node1 = bucketAtIndex(hashToIndex(a1bHash));
+ const Node* const node2 = bucketAtIndex(hashToIndex(a2bHash));
+
+ if (node1 != 0 && node2 != 0 && mRing.monomialIsTwoProductsOfHintTrue
+ (a1, a2, b, node1->mono, node2->mono)
+ )
+ return std::make_pair(&node1->value, &node2->value);
+ else
+ return std::make_pair(findProduct(a1, b), findProduct(a2, b));
+ }
+
+ void insert(const value_type& value) {
+ Node* node = static_cast<Node*>(mNodeAlloc.alloc());
+ const size_t index = hashToIndex(mRing.monomialHashValue(value.first));
+ {
+ Monomial nodeTmp(node->mono);
+ ring().monomialCopy(value.first, nodeTmp);
+ }
+ new (&node->value) mapped_type(value.second);
+ node->next = bucketAtIndex(index);
+ mBuckets[index] = node;
+ ++mEntryCount;
+ }
+
+ void clear() {
+ std::fill_n(mBuckets, bucketCount(), static_cast<Node*>(0));
+ mNodeAlloc.freeAllBuffers();
+ mEntryCount = 0;
+ }
+
+private:
+ size_t hashToIndex(HashValue hash) const {
+ const auto index = hash & mHashToIndexMask;
+ MATHICGB_ASSERT(index == hash % bucketCount());
+ return index;
+ }
+
+ Node* bucketAtIndex(size_t index) {
+ MATHICGB_ASSERT(index < bucketCount());
+ return mBuckets[index];
+ }
+
+ const Node* bucketAtIndex(size_t index) const {
+ MATHICGB_ASSERT(index < bucketCount());
+ return mBuckets[index];
+ }
+
+ const HashValue mHashToIndexMask;
+ Node** const mBuckets;
+ const PolyRing& mRing;
+ memt::BufferPool mNodeAlloc; // nodes are allocated from here.
+ size_t mEntryCount;
+};
+
+
+
namespace MonomialMapInternal {
// The map type MapClass is defined here. This is here in
// this namespace to avoid cluttering the class definition with
// a lot of ifdef's.
-#ifdef MATHICGB_USE_CUSTOM_HASH
template<class MTT>
class MapClass {
public:
@@ -51,7 +236,7 @@ namespace MonomialMapInternal {
};
public:
- MapClass(const PolyRing& ring):
+ MapClass(const PolyRing& ring, size_t bucketCount = 400000):
mRing(ring),
mTable(),
mNodeAlloc(sizeof(Node) - sizeof(exponent) + ring.maxMonomialByteSize())
@@ -62,58 +247,23 @@ namespace MonomialMapInternal {
growTable();
}
- Map& map() {return *this;}
- const Map& map() const {return *this;}
const PolyRing& ring() const {return mRing;}
- mapped_type* find(const_monomial mono) {
- const HashValue monoHash = mRing.monomialHashValue(mono);
- Node* node = entry(hashToIndex(monoHash));
- for (; node != 0; node = node->next) {
- // To my surprise, it seems to be faster to comment out this branch.
- // I guess the hash table has too few collisions to make it worth it.
- //if (monoHash != mRing.monomialHashValue(node->mono))
- // continue;
- if (mRing.monomialEqualHintTrue(mono, node->mono))
- return &node->value;
- }
- return 0;
- }
-
- MATHICGB_INLINE mapped_type* findProduct(
+ MATHICGB_INLINE const mapped_type* findProduct(
const const_monomial a,
const const_monomial b
- ) {
- const HashValue abHash = mRing.monomialHashOfProduct(a, b);
- Node* node = entry(hashToIndex(abHash));
- for (; node != 0; node = node->next) {
- // To my surprise, it seems to be faster to comment out this branch.
- // I guess the hash table has too few collisions to make it worth it.
- //if (abHash != mRing.monomialHashValue(node->mono))
- // continue;
- if (mRing.monomialIsProductOfHintTrue(a, b, node->mono))
- return &node->value;
- }
- return 0;
+ ) const {
+ return reader().findProduct(a, b);
}
/// As findProduct but looks for a1*b and a2*b at one time.
- MATHICGB_INLINE std::pair<mapped_type*, mapped_type*> findTwoProducts(
+ MATHICGB_INLINE
+ std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
const const_monomial a1,
const const_monomial a2,
const const_monomial b
- ) {
- const HashValue a1bHash = mRing.monomialHashOfProduct(a1, b);
- const HashValue a2bHash = mRing.monomialHashOfProduct(a2, b);
- Node* const node1 = entry(hashToIndex(a1bHash));
- Node* const node2 = entry(hashToIndex(a2bHash));
-
- if (node1 != 0 && node2 != 0 && mRing.monomialIsTwoProductsOfHintTrue
- (a1, a2, b, node1->mono, node2->mono)
- )
- return std::make_pair(&node1->value, &node2->value);
- else
- return std::make_pair(findProduct(a1, b), findProduct(a2, b));
+ ) const {
+ return reader().findTwoProducts(a1, a2, b);
}
void insert(const value_type& value) {
@@ -140,6 +290,102 @@ namespace MonomialMapInternal {
size_t size() const {return mEntryCount;}
+ class MapReader {
+ public:
+ const mapped_type* find(const const_monomial mono) const {
+ const HashValue monoHash = mRing.monomialHashValue(mono);
+ const Node* node = entry(hashToIndex(monoHash));
+ for (; node != 0; node = node->next) {
+ // To my surprise, it seems to be faster to comment out this branch.
+ // I guess the hash table has too few collisions to make it worth it.
+ //if (monoHash != mRing.monomialHashValue(node->mono))
+ // continue;
+ if (mRing.monomialEqualHintTrue(mono, node->mono))
+ return &node->value;
+ }
+ return 0;
+ }
+
+ const PolyRing& ring() {return mRing;}
+
+ size_t bucketCount() const {
+ MATHICGB_ASSERT(mHashToIndexMask <
+ std::numeric_limits<decltype(mHashToIndexMask)>::max());
+ return mHashToIndexMask + 1;
+ }
+
+ MATHICGB_INLINE const mapped_type* findProduct(
+ const const_monomial a,
+ const const_monomial b
+ ) const {
+ const HashValue abHash = mRing.monomialHashOfProduct(a, b);
+ const Node* node = entry(hashToIndex(abHash));
+ for (; node != 0; node = node->next) {
+ // To my surprise, it seems to be faster to comment out this branch.
+ // I guess the hash table has too few collisions to make it worth it.
+ //if (abHash != mRing.monomialHashValue(node->mono))
+ // continue;
+ if (mRing.monomialIsProductOfHintTrue(a, b, node->mono))
+ return &node->value;
+ }
+ return 0;
+ }
+
+ /// As findProduct but looks for a1*b and a2*b at one time.
+ MATHICGB_INLINE
+ std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
+ const const_monomial a1,
+ const const_monomial a2,
+ const const_monomial b
+ ) const {
+ const HashValue a1bHash = mRing.monomialHashOfProduct(a1, b);
+ const HashValue a2bHash = mRing.monomialHashOfProduct(a2, b);
+ const Node* const node1 = entry(hashToIndex(a1bHash));
+ const Node* const node2 = entry(hashToIndex(a2bHash));
+
+ if (node1 != 0 && node2 != 0 && mRing.monomialIsTwoProductsOfHintTrue
+ (a1, a2, b, node1->mono, node2->mono)
+ )
+ return std::make_pair(&node1->value, &node2->value);
+ else
+ return std::make_pair(findProduct(a1, b), findProduct(a2, b));
+ }
+
+ private:
+ friend class MapClass<MTT>;
+ size_t hashToIndex(const HashValue hash) const {
+ const auto index = hash & mHashToIndexMask;
+ MATHICGB_ASSERT(index == hash % bucketCount());
+ return index;
+ }
+
+ const Node* entry(const size_t index) const {
+ MATHICGB_ASSERT(index < bucketCount());
+ return mTable[index];
+ }
+
+ MapReader(
+ const PolyRing& ring,
+ const Node* const* const table,
+ const HashValue mHashToIndexMask
+ ):
+ mRing(ring),
+ mTable(table),
+ mHashToIndexMask(mHashToIndexMask) {}
+
+ const PolyRing& mRing;
+ const Node* const* const mTable;
+ const HashValue mHashToIndexMask;
+ };
+
+ const mapped_type* find(const const_monomial mono) const {
+ return reader().find(mono);
+ }
+
+ const MapReader reader() const {
+ return MapReader(ring(), mTable.data(), mHashToIndexMask);
+ }
+
private:
size_t hashToIndex(HashValue hash) const {
const auto index = hash & mHashToIndexMask;
@@ -205,205 +451,86 @@ namespace MonomialMapInternal {
std::vector<Node*> mTable;
memt::BufferPool mNodeAlloc; // nodes are allocated from here.
};
-
-#elif defined(MATHICGB_USE_STD_HASH)
- class Hash {
- public:
- Hash(const PolyRing& ring): mRing(ring) {}
- size_t operator()(const_monomial m) const {
- return mRing.monomialHashValue(m);
- }
- const PolyRing& ring() const {return mRing;}
-
- private:
- const PolyRing& mRing;
- };
-
- class Equal {
- public:
- Equal(const PolyRing& ring): mRing(ring) {}
- size_t operator()(const_monomial a, const_monomial b) const {
- return mRing.monomialEQ(a, b);
- }
- const PolyRing& ring() const {return mRing;}
-
- private:
- const PolyRing& mRing;
- };
-
- // This has to be a template to support rebind().
- template<class T>
- class TemplateHashAllocator {
- public:
- typedef T value_type;
- typedef T* pointer;
- typedef T& reference;
- typedef const T* const_pointer;
- typedef const T& const_reference;
- typedef ::size_t size_type;
- typedef ::ptrdiff_t difference_type;
-
- template<class T2>
- struct rebind {
- typedef TemplateHashAllocator<T2> other;
- };
-
- TemplateHashAllocator() {}
- TemplateHashAllocator(memt::Arena& arena): mArena(arena) {}
- template<class X>
- TemplateHashAllocator(const TemplateHashAllocator<X>& a):
- mArena(a.arena()) {}
- TemplateHashAllocator(const TemplateHashAllocator<T>& a):
- mArena(a.arena()) {}
-
- pointer address(reference x) {return &x;}
- const_pointer address(const_reference x) const {return &x;}
- pointer allocate(size_type n, void* hint = 0) {
- return static_cast<pointer>(mArena.alloc(sizeof(T) * n));
- }
- void deallocate(pointer p, size_t n) {}
- size_type max_size() const {return std::numeric_limits<size_type>::max();}
- void construct(pointer p, const_reference val) {new (p) T(val);}
- void destroy(pointer p) {p->~T();}
- memt::Arena& arena() const {return mArena;}
-
- private:
- mutable memt::Arena& mArena;
- };
-
- template<class MTT>
- class MapClass {
- public:
- typedef TemplateHashAllocator<std::pair<const const_monomial, MTT>>
- HashAllocator;
- typedef std::unordered_map<const_monomial, MTT, Hash, Equal, HashAllocator>
- Map;
- typedef typename Map::iterator iterator;
- typedef typename Map::const_iterator const_iterator;
- typedef typename Map::value_type value_type;
-
- MapClass(const PolyRing& ring):
- mArena(),
- mMap(100, Hash(ring), Equal(ring), HashAllocator(mArena)),
- mTmp(ring.allocMonomial())
- {
- mMap.max_load_factor(0.3f);
- }
-
- ~MapClass() {
- ring().freeMonomial(mTmp);
- }
-
- Map& map() {return mMap;}
- const Map& map() const {return mMap;}
- const PolyRing& ring() const {return mMap.key_eq().ring();}
-
- value_type* findProduct(const_monomial a, const_monomial b) {
- ring().setGivenHash(mTmp, ring().monomialHashOfProduct(a, b));
- size_t bucket = mMap.bucket(mTmp);
- auto stop = mMap.end(bucket);
- for (auto it = mMap.begin(bucket); it != stop; ++it)
- if (ring().monomialIsProductOf(a, b, it->first))
- return &*it;
- return 0;
- }
-
- private:
- memt::Arena mArena;
- Map mMap;
- monomial mTmp;
- };
-#elif defined(MATHICGB_USE_CUSTOM_HASH)
-#else
- /// We need SOME ordering to make std::map work.
- class ArbitraryOrdering {
- public:
- ArbitraryOrdering(const PolyRing& ring): mRing(ring) {}
- bool operator()(const_monomial a, const_monomial b) const {
- return mRing.monomialLT(a, b);
- }
- const PolyRing& ring() const {return mRing;}
-
- private:
- const PolyRing& mRing;
- };
-
- template<class MTT>
- class MapClass {
- public:
- typedef std::map<const_monomial, MTT, ArbitraryOrdering> Map;
-
- MapClass(const PolyRing& ring): mMap(ArbitraryOrdering(ring)) {}
- Map& map() {return mMap;}
- const Map& map() const {return mMap;}
- const PolyRing& ring() const {return mMap.key_cmp().ring();}
-
- private:
- Map mMap;
- };
-#endif
}
+
template<class MTT>
class MonomialMap {
public:
typedef MTT mapped_type;
- typedef MonomialMapInternal::MapClass<MTT> MapType;
+ //typedef MonomialMapInternal::MapClass<MTT> MapType;
+ typedef FixedSizeMonomialMap<MTT> MapType;
//typedef typename MapType::Map::iterator iterator;
//typedef typename MapType::Map::const_iterator const_iterator;
- typedef typename MapType::Map::value_type value_type;
+ typedef typename MapType::value_type value_type;
+
+ /// A snapshot of a map. Later updates to the map may
+ /// or may not ever become reflected in this snapshot. The acquire/release
+ /// overhead for reading from the table is only performed once per
+ /// snapshot while it is performed every time when reading directly
+ /// from the map.
+ class SnapshotReader {
+ public:
+ SnapshotReader(const MonomialMap<MTT>& map): mMap(&map.mMap) {}
+ void update(const MonomialMap<MTT>& map) {mMap = &map.mMap;}
- MonomialMap(const PolyRing& ring): mMap(ring) {}
+ const mapped_type* find(const_monomial m) const {
+ return mMap->find(m);
+ }
-/* iterator begin() {return map().begin();}
- const_iterator begin() const {return map().begin();}
- iterator end() {return map().end();}
- const_iterator end() const {return map().end();}*/
+ const mapped_type* findProduct(
+ const const_monomial a,
+ const const_monomial b
+ ) const {
+ return mMap->findProduct(a, b);
+ }
- mapped_type* find(const_monomial m) {return mMap.find(m);}
+ MATHICGB_INLINE
+ std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
+ const const_monomial a1,
+ const const_monomial a2,
+ const const_monomial b
+ ) const {
+ return mMap->findTwoProducts(a1, a2, b);
+ }
- mapped_type* findProduct(const_monomial a, const_monomial b) {
- return mMap.findProduct(a, b);
- }
+ private:
+ SnapshotReader(const FixedSizeMonomialMap<MTT>& map): mMap(&map) {}
+ const FixedSizeMonomialMap<MTT>* mMap;
+ };
- MATHICGB_INLINE std::pair<mapped_type*, mapped_type*> findTwoProducts(
- const const_monomial a1,
- const const_monomial a2,
- const const_monomial b
- ) {
- return mMap.findTwoProducts(a1, a2, b);
- }
+ MonomialMap(const PolyRing& ring): mMap(200 * 1000, ring) {}
const mapped_type* find(const_monomial m) const {
- return const_cast<MonomialMap&>(*this).find(m);
+ return mMap.find(m);
}
- const mapped_type* findProduct(const_monomial a, const_monomial b) const {
- return const_cast<MonomialMap&>(*this).findProduct(a, b);
+ const mapped_type* findProduct(
+ const const_monomial a,
+ const const_monomial b
+ ) const {
+ return mMap.findProduct(a, b);
}
- MATHICGB_INLINE const std::pair<const mapped_type*, const mapped_type*>
- findTwoProducts(
+ MATHICGB_INLINE
+ std::pair<const mapped_type*, const mapped_type*> findTwoProducts(
const const_monomial a1,
const const_monomial a2,
const const_monomial b
) const {
- return const_cast<MonomialMap&>(*this).findTwoProducts(a1, a2, b);
+ return mMap.findTwoProducts(a1, a2, b);
}
- size_t size() const {return map().size();}
- void clear() {map().clear();}
+ size_t size() const {return mMap.size();}
+ void clear() {mMap.clear();}
void insert(const value_type& val) {
- map().insert(val);
+ mMap.insert(val);
}
inline const PolyRing& ring() const {return mMap.ring();}
private:
- typename MapType::Map& map() {return mMap.map();}
- const typename MapType::Map& map() const {return mMap.map();}
-
MapType mMap;
};
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index 0f357c4..ddb260f 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -699,8 +699,7 @@ MATHICGB_INLINE bool PolyRing::monomialIsTwoProductsOfHintTrue(
orOfXor |= (A1B ^ (A1 + B)) | (A2B ^ (A2 + B));
}
MATHICGB_ASSERT((orOfXor == 0) ==
- monomialIsProductOf(a1, b, a1b) &&
- monomialIsProductOf(a2, b, a2b));
+ (monomialIsProductOf(a1, b, a1b) && monomialIsProductOf(a2, b, a2b)));
return orOfXor == 0;
}
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
index 7b050d8..71d9d4a 100755
--- a/src/mathicgb/QuadMatrixBuilder.hpp
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -183,6 +183,12 @@ class QuadMatrixBuilder {
// *** Querying columns
+ typedef const MonomialMap<LeftRightColIndex>::SnapshotReader
+ ColSnapshotReader;
+ const MonomialMap<LeftRightColIndex>& columnToIndexMap() const {
+ return mMonomialToCol;
+ }
+
/** Returns a column for the findThis monomial. Searches on both the
left and right side. Returns an invalid index if no such column
exists. */
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git
More information about the debian-science-commits
mailing list