[mathicgb] 81/393: Parallelized the sorting and reordering of matrices. Also added a set of macroes that give a way to tell the optimizer extra information, such as saying that two pointers are not aliases.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:35 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 0921cbe90474fe396f66694724c5ecd862824e3b
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Thu Oct 25 20:58:23 2012 +0200

    Parallelized the sorting and reordering of matrices. Also added a set of macroes that give a way to tell the optimizer extra information, such as saying that two pointers are not aliases.
---
 src/mathicgb/F4MatrixBuilder.cpp   |  3 +-
 src/mathicgb/F4MatrixReducer.cpp   |  9 ++--
 src/mathicgb/GroebnerBasis.hpp     | 18 ++++----
 src/mathicgb/MonTableDivList.hpp   |  4 +-
 src/mathicgb/Poly.cpp              |  2 +-
 src/mathicgb/PolyRing.hpp          |  8 ++--
 src/mathicgb/QuadMatrix.cpp        |  6 ++-
 src/mathicgb/QuadMatrix.hpp        |  3 +-
 src/mathicgb/QuadMatrixBuilder.cpp | 71 +++++++++++++++++++++++++++++
 src/mathicgb/QuadMatrixBuilder.hpp |  5 +++
 src/mathicgb/SPairs.cpp            |  2 +-
 src/mathicgb/SparseMatrix.hpp      |  2 +-
 src/mathicgb/stdinc.h              | 91 +++++++++++++++++++++++++++++++-------
 src/test/FreeModuleOrderTest.cpp   |  6 +--
 14 files changed, 180 insertions(+), 50 deletions(-)

diff --git a/src/mathicgb/F4MatrixBuilder.cpp b/src/mathicgb/F4MatrixBuilder.cpp
index f7da87d..fed4dfa 100755
--- a/src/mathicgb/F4MatrixBuilder.cpp
+++ b/src/mathicgb/F4MatrixBuilder.cpp
@@ -225,8 +225,7 @@ void F4MatrixBuilder::buildMatrixAndClear(QuadMatrix& matrix) {
 #endif
 
 
-  mBuilder.sortColumnsLeft(mBasis.order());
-  mBuilder.sortColumnsRight(mBasis.order());
+  mBuilder.sortColumnsLeftRightParallel(mBasis.order(), mThreadCount);
   mBuilder.buildMatrixAndClear(matrix);
 }
 
diff --git a/src/mathicgb/F4MatrixReducer.cpp b/src/mathicgb/F4MatrixReducer.cpp
index ca658ff..bdae9d7 100755
--- a/src/mathicgb/F4MatrixReducer.cpp
+++ b/src/mathicgb/F4MatrixReducer.cpp
@@ -523,13 +523,10 @@ void myReduceToEchelonForm5
       MATHICGB_ASSERT(reduced.colCount() == colCount);
       size_t const row = nextReducers[i].second;
 
-#ifdef MATHICGB_DEBUG
-      size_t const col = nextReducers[i].first;
-#endif
-      MATHICGB_ASSERT(col == nextReducers[i].first);
-      MATHICGB_ASSERT(columnHasPivot[col]);
+      MATHICGB_ASSERT(static_cast<bool>
+        (columnHasPivot[nextReducers[i].first]));
       MATHICGB_ASSERT(dense[row].colCount() == colCount);
-      MATHICGB_ASSERT(dense[row][col] == 1); // already normalized
+      MATHICGB_ASSERT(dense[row][nextReducers[i].first] == 1); // already normalized
       MATHICGB_ASSERT(reduced.rowCount() == i);
       MATHICGB_ASSERT(!isPivotRow[row]);
 
diff --git a/src/mathicgb/GroebnerBasis.hpp b/src/mathicgb/GroebnerBasis.hpp
index 51e291b..b0c928c 100644
--- a/src/mathicgb/GroebnerBasis.hpp
+++ b/src/mathicgb/GroebnerBasis.hpp
@@ -189,18 +189,18 @@ private:
 
 inline int GroebnerBasis::ratioCompare(size_t a, size_t b) const {
   if (mUseRatioRank) {
-#ifdef DEBUG
+#ifdef MATHICGB_DEBUG
     int const value =
       order().signatureCompare(getSigLeadRatio(a), getSigLeadRatio(b));
 #endif
     if (mRatioRanks[a] < mRatioRanks[b]) {
-      ASSERT(value == LT);
+      MATHICGB_ASSERT_NO_ASSUME(value == LT);
       return LT;
     } else if (mRatioRanks[a] > mRatioRanks[b]) {
-      ASSERT(value == GT);
+      MATHICGB_ASSERT_NO_ASSUME(value == GT);
       return GT;
     } else {
-      ASSERT(value == EQ);
+      MATHICGB_ASSERT_NO_ASSUME(value == EQ);
       return EQ;
     }
   } else {
@@ -208,7 +208,7 @@ inline int GroebnerBasis::ratioCompare(size_t a, size_t b) const {
     ring().monomialDivideToNegative(getSignature(b), getLeadMonomial(b), mTmp);
     ring().monomialMultTo(mTmp, getLeadMonomial(a));
     int value = order().signatureCompare(getSignature(a), mTmp);
-    ASSERT(value ==
+    MATHICGB_ASSERT(value ==
       order().signatureCompare(getSigLeadRatio(a), getSigLeadRatio(b)));
     return value;
   }
@@ -222,19 +222,19 @@ inline int GroebnerBasis::StoredRatioCmp::compare(size_t be) const {
 #endif
     GroebnerBasis::Rank otherRank = mBasis.ratioRank(be);
     if (mRatioRank < otherRank) {
-      ASSERT(value == LT);
+      MATHICGB_ASSERT_NO_ASSUME(value == LT);
       return LT;
     } else if (mRatioRank > otherRank) {
-      ASSERT(value == GT);
+      MATHICGB_ASSERT_NO_ASSUME(value == GT);
       return GT;
     } else {
-      ASSERT(value == EQ);
+      MATHICGB_ASSERT_NO_ASSUME(value == EQ);
       return EQ;
     }
   } else {
     mBasis.ring().monomialMult(mRatio, mBasis.getLeadMonomial(be), mTmp);
     int value = mBasis.order().signatureCompare(mTmp, mBasis.getSignature(be));
-    ASSERT(value ==
+    MATHICGB_ASSERT(value ==
       mBasis.order().signatureCompare(mRatio, mBasis.getSigLeadRatio(be)));
     return value;
   }
diff --git a/src/mathicgb/MonTableDivList.hpp b/src/mathicgb/MonTableDivList.hpp
index 17ad7be..4f3e628 100644
--- a/src/mathicgb/MonTableDivList.hpp
+++ b/src/mathicgb/MonTableDivList.hpp
@@ -49,7 +49,7 @@ public:
 
   size_t getVarCount() const {return _varCount;}
 
-  NO_PINLINE Exponent getExponent(const Monomial& m, size_t var) const {
+  Exponent getExponent(const Monomial& m, size_t var) const {
     ++_expQueryCount;
     return R->monomialExponent(m, var);
   }
@@ -67,7 +67,7 @@ public:
         return true;
       if (getExponent(b, var) < getExponent(a, var))
         return false;
-        }
+    }
     return false;
   }
 
diff --git a/src/mathicgb/Poly.cpp b/src/mathicgb/Poly.cpp
index ca4f30e..9ab4221 100755
--- a/src/mathicgb/Poly.cpp
+++ b/src/mathicgb/Poly.cpp
@@ -108,7 +108,7 @@ void Poly::makeMonic() {
   R->coefficientReciprocalTo(c);
   for (auto i = coeffs.begin(); i != coeffs.end(); i++)
     R->coefficientMultTo(*i, c);
-  MATHICGB_ASSERT(R->coefficientIsOne(getLeadCoefficient()))
+  MATHICGB_ASSERT(R->coefficientIsOne(getLeadCoefficient()));
 }
 
 bool operator==(const Poly &a, const Poly &b)
diff --git a/src/mathicgb/PolyRing.hpp b/src/mathicgb/PolyRing.hpp
index be6c4fa..b81be5c 100755
--- a/src/mathicgb/PolyRing.hpp
+++ b/src/mathicgb/PolyRing.hpp
@@ -56,7 +56,7 @@ T modularInverse(T a, T modulus) {
   }
   MATHICGB_ASSERT(x >= 1);
   MATHICGB_ASSERT(x < modulus);
-  MATHICGB_ASSERT((static_cast<uint64>(origA) * x) % modulus == 1);
+  MATHICGB_ASSERT_NO_ASSUME((static_cast<uint64>(origA) * x) % modulus == 1);
   return x;
 }
 
@@ -665,11 +665,9 @@ inline bool PolyRing::monomialIsProductOfHintTrue(
     std::memcpy(&AB, &ab[i], 8);
     orOfXor |= AB ^ (A + B);
   }
-  MATHICGB_ASSERT((orOfXor == 0) == monomialIsProductOf(a, b, ab))
+  MATHICGB_ASSERT((orOfXor == 0) == monomialIsProductOf(a, b, ab));
 
-
-  return orOfXor == 0;
-  
+  return orOfXor == 0; 
 }
 
 inline bool PolyRing::monomialIsProductOf(
diff --git a/src/mathicgb/QuadMatrix.cpp b/src/mathicgb/QuadMatrix.cpp
index ae13b61..a820c35 100755
--- a/src/mathicgb/QuadMatrix.cpp
+++ b/src/mathicgb/QuadMatrix.cpp
@@ -5,8 +5,10 @@
 #include <sstream>
 #include <mathic.h>
 
-#ifdef MATHICGB_DEBUG
 bool QuadMatrix::debugAssertValid() const {
+#ifndef MATHICGB_DEBUG
+  return true;
+#else
   MATHICGB_ASSERT(topLeft.colCount() == bottomLeft.colCount());
   MATHICGB_ASSERT(topLeft.rowCount() == topRight.rowCount());
   MATHICGB_ASSERT(topLeft.colCount() == leftColumnMonomials.size());
@@ -15,8 +17,8 @@ bool QuadMatrix::debugAssertValid() const {
   MATHICGB_ASSERT(bottomRight.rowCount() == bottomLeft.rowCount());
   MATHICGB_ASSERT(bottomRight.colCount() == rightColumnMonomials.size());   
   return true;
-}
 #endif
+}
 
 void QuadMatrix::print(std::ostream& out) const {
   MATHICGB_ASSERT(debugAssertValid());
diff --git a/src/mathicgb/QuadMatrix.hpp b/src/mathicgb/QuadMatrix.hpp
index d7282ad..12dceff 100755
--- a/src/mathicgb/QuadMatrix.hpp
+++ b/src/mathicgb/QuadMatrix.hpp
@@ -47,9 +47,8 @@ public:
   /// TODO: Actually only coarsely sorts the top rows right now.
   QuadMatrix toCanonical() const;
 
-#ifdef MATHICGB_DEBUG
+  /// Asserts internal invariants if asserts are turned on.
   bool debugAssertValid() const;
-#endif
 
 private:
   QuadMatrix(const QuadMatrix&); // not available
diff --git a/src/mathicgb/QuadMatrixBuilder.cpp b/src/mathicgb/QuadMatrixBuilder.cpp
index ecda6d8..73033f5 100755
--- a/src/mathicgb/QuadMatrixBuilder.cpp
+++ b/src/mathicgb/QuadMatrixBuilder.cpp
@@ -134,6 +134,45 @@ namespace {
     const FreeModuleOrder& mOrder;
   };
 
+  std::vector<SparseMatrix::ColIndex> sortColumnMonomialsAndMakePermutation(
+    const FreeModuleOrder& order,
+    std::vector<monomial>& monomials
+  ) {
+    typedef SparseMatrix::ColIndex ColIndex;
+    MATHICGB_ASSERT(monomials.size() <= std::numeric_limits<ColIndex>::max());
+    const ColIndex colCount = static_cast<ColIndex>(monomials.size());
+    // Monomial needs to be non-const as we are going to put these
+    // monomials back into the vector of monomials which is not const.
+    std::vector<std::pair<monomial, ColIndex>> columns;
+    columns.reserve(colCount);
+    for (ColIndex col = 0; col < colCount; ++col)
+      columns.push_back(std::make_pair(monomials[col], col));
+    std::sort(columns.begin(), columns.end(), ColumnComparer(order));
+
+    // Apply sorting permutation to monomials. This is why it is necessary to
+    // copy the values in monomial out of there: in-place application of a
+    // permutation is messy.
+    MATHICGB_ASSERT(columns.size() == colCount);
+    MATHICGB_ASSERT(monomials.size() == colCount);
+    for (size_t col = 0; col < colCount; ++col) {
+      MATHICGB_ASSERT(col == 0 ||  order.signatureCompare
+                      (columns[col - 1].first, columns[col].first) == GT);
+      monomials[col] = columns[col].first;
+    }
+
+    // Construct permutation of indices to match permutation of monomials
+    std::vector<ColIndex> permutation(colCount);
+    for (ColIndex col = 0; col < colCount; ++col) {
+      // The monomial for column columns[col].second is now the
+      // monomial for col, so we need the inverse map for indices.
+      permutation[columns[col].second] = col;
+    }
+
+    return std::move(permutation);
+  }
+
+
+
   // The purpose of this function is to avoid code duplication for
   // left/right variants.
   void sortColumns
@@ -185,6 +224,38 @@ void QuadMatrixBuilder::sortColumnsRight(const FreeModuleOrder& order) {
   sortColumns(order, mMonomialsRight, mTopRight, mBottomRight);
 }
 
+void QuadMatrixBuilder::sortColumnsLeftRightParallel(
+  const FreeModuleOrder& order,
+  int threadCount
+) {
+  std::vector<ColIndex> leftPermutation;
+  std::vector<ColIndex> rightPermutation;
+
+#pragma omp parallel for num_threads(threadCount) schedule(static)
+  for (OMPIndex i = 0; i < 2; ++i) {
+    if (i == 0)
+      leftPermutation =
+        sortColumnMonomialsAndMakePermutation(order, mMonomialsLeft);
+    else 
+      rightPermutation =
+        sortColumnMonomialsAndMakePermutation(order, mMonomialsRight);
+  }
+
+#pragma omp parallel for num_threads(threadCount) schedule(dynamic)
+  for (OMPIndex i = 0; i < 4; ++i) {
+    if (i == 0)
+      mTopRight.applyColumnMap(rightPermutation);
+    else if (i == 1)
+      mBottomRight.applyColumnMap(rightPermutation);
+    else if (i == 2)
+      mTopLeft.applyColumnMap(leftPermutation);
+    else {
+      MATHICGB_ASSERT(i == 3);
+      mBottomLeft.applyColumnMap(leftPermutation);
+    }
+  }
+}
+
 void QuadMatrixBuilder::print(std::ostream& out) const {
   mathic::ColumnPrinter printer;
   printer.addColumn(true, "", "");
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
index 9e07100..8992d23 100755
--- a/src/mathicgb/QuadMatrixBuilder.hpp
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -165,6 +165,11 @@ class QuadMatrixBuilder {
     this monomial on the left or on the right. */
   LeftRightColIndex createColumnRight(const_monomial monomialToBeCopied);
 
+  /// As calling sortColumnsLeft() and sortColumnsRight(), but performs
+  /// the operations in parallel using up to threadCount threads.
+  void sortColumnsLeftRightParallel
+    (const FreeModuleOrder& order, int threadCount);
+
   /** Sorts the left columns to be decreasing with respect to
     order. Also updates the column indices already in the matrix to
     reflect the new ordering. */
diff --git a/src/mathicgb/SPairs.cpp b/src/mathicgb/SPairs.cpp
index d39d720..ee3e277 100755
--- a/src/mathicgb/SPairs.cpp
+++ b/src/mathicgb/SPairs.cpp
@@ -529,7 +529,7 @@ bool SPairs::advancedBuchbergerLcmCriterionSlow(size_t a, size_t b) const {
       } else {
         // At this point we have found an edge between something a node to
         // a and a node connected to b. So a and b are connected.
-        ASSERT(graph[i].second != node.second)
+        ASSERT(graph[i].second != node.second);
         applies = true;
         break;
       }
diff --git a/src/mathicgb/SparseMatrix.hpp b/src/mathicgb/SparseMatrix.hpp
index 57beae0..426b937 100755
--- a/src/mathicgb/SparseMatrix.hpp
+++ b/src/mathicgb/SparseMatrix.hpp
@@ -276,7 +276,7 @@ public:
 
 
 private:
-  NO_INLINE void growEntryCapacity();
+  MATHICGB_NO_INLINE void growEntryCapacity();
 
   /// Contains information about a row in the matrix.
   struct Row {
diff --git a/src/mathicgb/stdinc.h b/src/mathicgb/stdinc.h
index 39ce87f..ef087a6 100755
--- a/src/mathicgb/stdinc.h
+++ b/src/mathicgb/stdinc.h
@@ -3,18 +3,51 @@
 #endif
 #define MATHICGB_STDINC_GUARD
 
-#ifdef PROFILE
-#define NO_PINLINE NO_INLINE
-#else
-#define NO_PINLINE
-#endif
+#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
+
+// Sometimes you know that a function will be called very rarely so you want to
+// tell the compiler not to inline it even if it could be inlined at only a
+// modest increase in code size. That is what MATHICGB_NO_INLINE does.
+#define MATHICGB_NO_INLINE __declspec(noinline)
+
+// Sometimes the compiler just will not inline functions that should
+// be inlined. Use sparingly --- preferably only if a profiler says
+// that a tiny often-called function consumes a significant amount of time.
+#define MATHICGB_INLINE __forceinline
+
+// Tells the compiler to always assume that the expression X is true.
+#define MATHICGB_ASSUME(X) __assume(X)
+
+// As MATHICGB_ASSUME, but might actually evaluate X at run-time if it has
+// side-effects. The point is that this can be used on compilers with no other
+// support for assuming things. So there is no difference on MS VC++.
+#define MATHICGB_ASSUME_AND_MAY_EVALUATE(X) __assume(X)
+
+// Tells the compiler that this function returns a pointer that is not an alias
+// for any other point that is currently valid in the program - like malloc.
+#define MATHICGB_RETURN_NO_ALIAS __declspec(restrict)
+
+// Tells the compiler that this function will never throw an exception.
+#define MATHICGB_NOTHROW __declspec(nothrow)
+
+// Tells the compiler that this function has no effects except the return value
+// and the return value depends only on the arguments and first-level
+// indirections of the arguments. (this is the common denominator of GCC
+// and MS VC++ capabilities)
+#define MATHICGB_PURE __declspec(noalias)
+
+// Tells the compiler that the return value of this function must be looked
+// at by the caller. For example this is appropriate for realloc.
+#define MATHICGB_MUST_CHECK_RETURN_VALUE
+
+// Tells the compiler that the current line of code cannot be reached.
+#define MATHICGB_UNREACHABLE __assume(false)
+
+// Tells the compiler that a variable that is a pointer (not a reference)
+// does not alias any other pointer that is used in the current scope.
+#define MATHICGB_RESTRICT __restrict
 
-#ifndef _MSC_VER
-#define NO_INLINE __attribute__ ((noinline))
-#endif
 
-#ifdef _MSC_VER // For Microsoft Compiler in Visual Studio C++.
-#define NO_INLINE __declspec(noinline)
 #pragma warning (disable: 4996) // std::copy on pointers is flagged as dangerous
 #pragma warning (disable: 4290) // VC++ ignores throw () specification.
 #pragma warning (disable: 4127) // Warns about using "while (true)".
@@ -22,12 +55,36 @@
 #pragma warning (disable: 4800) // Warns on int to bool conversion.
 #pragma warning (disable: 4146) // Warns on unary minus on unsigned (bit trick)
 
-
 // This warning warns about using the this pointer in base member
 // initializer lists. This is a pretty good warning as that can
 // obviously easily go wrong, but it is pretty useful to do as well,
 // so the warning is turned off.
 #pragma warning (disable: 4355)
+
+#elif defined (__GNUC__) // GCC compiler
+
+#define MATHICGB_NO_INLINE __attribute__((noinline))
+#define MATHICGB_INLINE __attribute__((always_inline)) inline
+#define MATHICGB_ASSUME(X)
+#define MATHICGB_ASSUME_AND_MAY_EVALUATE(X) do {if(!(X)){MATHICGB_UNREACHABLE;}while(0)}
+#define MATHICGB_RETURN_NO_ALIAS __attribute__(malloc)
+#define MATHICGB_NOTHROW __attribute__(nothrow)
+#define MATHICGB_PURE __attribute__(pure)
+#define MATHICGB_MUST_CHECK_RETURN_VALUE __attribute__(warn_unused_result)
+#define MATHICGB_UNREACHABLE __builtin_unreachable()
+
+#else
+
+#define MATHICGB_NO_INLINE
+#define MATHICGB_INLINE inline
+#define MATHICGB_ASSUME(X)
+#define MATHICGB_ASSUME_AND_MAY_EVALUATE(X)
+#define MATHICGB_RETURN_NO_ALIAS
+#define MATHICGB_NOTHROW
+#define MATHICGB_PURE
+#define MATHICGB_MUST_CHECK_RETURN_VALUE
+#define MATHICGB_UNREACHABLE
+
 #endif
 
 #include <cstddef>
@@ -40,15 +97,17 @@
 #define DEBUG
 #include <iostream> // Useful for debugging.
 #include <cassert>
-#define ASSERT(X) assert(X);
-#define IF_DEBUG(X) X
+#define MATHICGB_ASSERT(X) do{assert(X);}while(0)
+#define MATHICGB_ASSERT_NO_ASSUME(X) MATHICGB_ASSERT(X)
+#define MATHICGB_IF_DEBUG(X) X
 #else
-#define ASSERT(X)
-#define IF_DEBUG(X)
+#define MATHICGB_ASSERT(X) MATHICGB_ASSUME(X)
+#define MATHICGB_ASSERT_NO_ASSUME(X)
+#define MATHICGB_IF_DEBUG(X)
 #endif
 // todo: eventually move all ASSERTs to MATHICGB_ASSERTs and then remove
 // ASSERT.
-#define MATHICGB_ASSERT(X) ASSERT(X)
+#define ASSERT(X) MATHICGB_ASSERT(X)
 
 #ifdef MATHICGB_SLOW_DEBUG
 // for asserts that take a long time.
diff --git a/src/test/FreeModuleOrderTest.cpp b/src/test/FreeModuleOrderTest.cpp
index 9984db7..e7a1ea3 100755
--- a/src/test/FreeModuleOrderTest.cpp
+++ b/src/test/FreeModuleOrderTest.cpp
@@ -36,12 +36,12 @@ void runTest(
     std::istringstream in(correctStr);
     for (size_t i = 0; i < answer.size(); ++i) {
       in >> answer[i];
-      ASSERT(in);
+      MATHICGB_ASSERT(!!in);
     }
   }
 
-  ASSERT(sigs.size() == pairs.size());
-  ASSERT(sigs.size() == pairs.size());
+  MATHICGB_ASSERT(sigs.size() == pairs.size());
+  MATHICGB_ASSERT(sigs.size() == pairs.size());
 
   std::unique_ptr<FreeModuleOrder> order
     (FreeModuleOrder::makeOrder(orderType, ideal.get()));

-- 
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