[GiNaC-list] [patch] Improve automatic algorithm selection in matrix::solve()
Vitaly Magerya
vmagerya at gmail.com
Mon Jun 18 00:32:45 CEST 2018
On 06/17/2018 11:57 PM, Richard B. Kreckel wrote:
> Two comments on your patch.
>
> 1) This line
> + for (auto && r : m) {
> looks unconventional due to it's using rvalue refs. Is this intentional?
> It doesn't make a difference in GCC (same asm code).
What I actually meant to write is "const auto &"; "auto &&" should
be the same, but shorter. I think the "&&" form was introduced
so that templates could seamlessly support both const and non-
const usage, but I found it useful in normal code too. In any
case, I'll make the "const" explicit (not that it matters in
this particular example).
> 2) Be careful when computing the matrix' density by counting non-zero
> elements: That loop breaks out on the first non-numeric element. The
> later decision on what yo use with density might be wrong. Maybe you
> want to compute numeric_flag and density in two separate loops?
Dammit. My mistake, sorry.
Here's the updated patch. I've additionally included a minor
update to the comment near solve_algo::markowitz definition.
-------------- next part --------------
From c4b8475e7b35891223009aa36610413164e7aac6 Mon Sep 17 00:00:00 2001
From: Vitaly Magerya <magv at tx97.net>
Date: Thu, 14 Jun 2018 14:31:28 +0200
Subject: [PATCH] Improve automatic algorithm selection for matrix::solve()
---
ginac/flags.h | 8 +++++---
ginac/matrix.cpp | 37 +++++++++++++++++++++++++++----------
2 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/ginac/flags.h b/ginac/flags.h
index cebc3fd4..f759dcd4 100644
--- a/ginac/flags.h
+++ b/ginac/flags.h
@@ -185,9 +185,11 @@ public:
bareiss,
/** Markowitz-ordered Gaussian elimination. Same as the usual
* Gaussian elimination, but with additional effort spent on
- * selection pivots that minimize fill-in. Much faster than the
- * methods above for large sparse matrices, marginally slower
- * than Gaussian elimination otherwise. */
+ * selecting pivots that minimize fill-in. Faster than the
+ * methods above for large sparse matrices (particularly with
+ * symbolic coefficients), otherwise slightly slower than
+ * Gaussian elimination.
+ */
markowitz
};
};
diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp
index 3a01da2d..fea52c62 100644
--- a/ginac/matrix.cpp
+++ b/ginac/matrix.cpp
@@ -1211,21 +1211,38 @@ matrix::echelon_form(unsigned algo, int n)
if (algo == solve_algo::automatic) {
// Gather some statistical information about the augmented matrix:
bool numeric_flag = true;
- for (auto & r : m) {
+ for (const auto & r : m) {
if (!r.info(info_flags::numeric)) {
numeric_flag = false;
break;
}
}
- // Bareiss (fraction-free) elimination is generally a good guess:
- algo = solve_algo::bareiss;
- // For row<3, Bareiss elimination is equivalent to division free
- // elimination but has more logistic overhead
- if (row<3)
- algo = solve_algo::divfree;
- // This overrides any prior decisions.
- if (numeric_flag)
- algo = solve_algo::gauss;
+ unsigned density = 0;
+ for (const auto & r : m) {
+ density += !r.is_zero();
+ }
+ unsigned ncells = col*row;
+ if (numeric_flag) {
+ // For numerical matrices Gauss is good, but Markowitz becomes
+ // better for large sparse matrices.
+ if ((ncells > 200) && (density < ncells/2)) {
+ algo = solve_algo::markowitz;
+ } else {
+ algo = solve_algo::gauss;
+ }
+ } else {
+ // For symbolic matrices Markowitz is good, but Bareiss/Divfree
+ // is better for small and dense matrices.
+ if ((ncells < 120) && (density*5 > ncells*3)) {
+ if (ncells <= 12) {
+ algo = solve_algo::divfree;
+ } else {
+ algo = solve_algo::bareiss;
+ }
+ } else {
+ algo = solve_algo::markowitz;
+ }
+ }
}
// Eliminate the augmented matrix:
std::vector<unsigned> colid(col);
--
2.13.6
More information about the GiNaC-list
mailing list