mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Improve product test coverage at critical code-path boundaries
libeigen/eigen!2285 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
@@ -152,6 +152,159 @@ void bug_gemv_run_small_cols() {
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
|
||||
// Systematic test of row-major GEMV run_small_cols and main run() remainder paths.
|
||||
// Varies cols from 1-7 (covers float PacketSize=8 and double PacketSize=4 boundaries)
|
||||
// and rows across values that exercise all n8/n4/n2/n1 remainder combinations.
|
||||
template <int>
|
||||
void gemv_small_cols_systematic() {
|
||||
const int test_cols[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
const int test_rows[] = {1, 2, 3, 4, 5, 7, 8, 9, 11, 13, 15, 16, 17, 25};
|
||||
|
||||
// Large stride forces n8=0, exercising all remainder-only paths.
|
||||
{
|
||||
const int stride = 5000; // 5000 * sizeof(double) = 40000 > 32000
|
||||
for (int ci = 0; ci < 7; ++ci) {
|
||||
for (int ri = 0; ri < 14; ++ri) {
|
||||
int rows = test_rows[ri], cols = test_cols[ci];
|
||||
Matrix<double, Dynamic, Dynamic, RowMajor> A_full(rows, stride);
|
||||
A_full.setRandom();
|
||||
auto A = A_full.leftCols(cols);
|
||||
VectorXd x = VectorXd::Random(cols);
|
||||
VectorXd y = A * x;
|
||||
VectorXd y_ref = VectorXd::Zero(rows);
|
||||
for (int i = 0; i < rows; ++i)
|
||||
for (int j = 0; j < cols; ++j) y_ref(i) += A(i, j) * x(j);
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normal stride (n8 active) to cover the 8-row main loop + remainders.
|
||||
for (int ci = 0; ci < 7; ++ci) {
|
||||
for (int ri = 0; ri < 14; ++ri) {
|
||||
int rows = test_rows[ri], cols = test_cols[ci];
|
||||
Matrix<double, Dynamic, Dynamic, RowMajor> A(rows, cols);
|
||||
A.setRandom();
|
||||
VectorXd x = VectorXd::Random(cols);
|
||||
VectorXd y = A * x;
|
||||
VectorXd y_ref = VectorXd::Zero(rows);
|
||||
for (int i = 0; i < rows; ++i)
|
||||
for (int j = 0; j < cols; ++j) y_ref(i) += A(i, j) * x(j);
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
|
||||
// Float with large stride: 9000 * sizeof(float) = 36000 > 32000
|
||||
{
|
||||
const int stride = 9000;
|
||||
for (int ci = 0; ci < 7; ++ci) {
|
||||
for (int ri = 0; ri < 14; ++ri) {
|
||||
int rows = test_rows[ri], cols = test_cols[ci];
|
||||
Matrix<float, Dynamic, Dynamic, RowMajor> A_full(rows, stride);
|
||||
A_full.setRandom();
|
||||
auto A = A_full.leftCols(cols);
|
||||
VectorXf x = VectorXf::Random(cols);
|
||||
VectorXf y = A * x;
|
||||
VectorXf y_ref = VectorXf::Zero(rows);
|
||||
for (int i = 0; i < rows; ++i)
|
||||
for (int j = 0; j < cols; ++j) y_ref(i) += A(i, j) * x(j);
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test the main row-major GEMV n8=0 path (not run_small_cols) with varied row counts.
|
||||
// The n8 threshold is stride*sizeof(Scalar) > 32000.
|
||||
template <int>
|
||||
void gemv_rowmajor_large_stride_varied_rows() {
|
||||
const int test_rows[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 25, 100};
|
||||
// Double: cols=5000 (5000*8 > 32000), enough cols to stay on main run() path.
|
||||
{
|
||||
const int cols = 5000;
|
||||
for (int ri = 0; ri < 16; ++ri) {
|
||||
int rows = test_rows[ri];
|
||||
Matrix<double, Dynamic, Dynamic, RowMajor> A(rows, cols);
|
||||
A.setRandom();
|
||||
VectorXd x = VectorXd::Random(cols);
|
||||
VectorXd y = A * x;
|
||||
VectorXd y_ref = VectorXd::Zero(rows);
|
||||
for (int i = 0; i < rows; ++i)
|
||||
for (int j = 0; j < cols; ++j) y_ref(i) += A(i, j) * x(j);
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
// Float: cols=9000 (9000*4 > 32000).
|
||||
{
|
||||
const int cols = 9000;
|
||||
for (int ri = 0; ri < 16; ++ri) {
|
||||
int rows = test_rows[ri];
|
||||
Matrix<float, Dynamic, Dynamic, RowMajor> A(rows, cols);
|
||||
A.setRandom();
|
||||
VectorXf x = VectorXf::Random(cols);
|
||||
VectorXf y = A * x;
|
||||
VectorXf y_ref = VectorXf::Zero(rows);
|
||||
for (int i = 0; i < rows; ++i)
|
||||
for (int j = 0; j < cols; ++j) y_ref(i) += A(i, j) * x(j);
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test extreme aspect ratios that exercise GEMV, outer-product, and thin-GEMM dispatch.
|
||||
template <int>
|
||||
void product_extreme_aspect_ratios() {
|
||||
const int sizes[] = {1, 2, 3, 4, 8, 16, 48, 64, 128};
|
||||
for (int si = 0; si < 9; ++si) {
|
||||
int s = sizes[si];
|
||||
for (int ki = 0; ki < 9; ++ki) {
|
||||
int k = sizes[ki];
|
||||
// Thin result: s x k * k x 2 (2-column GEMM)
|
||||
{
|
||||
MatrixXd A = MatrixXd::Random(s, k);
|
||||
MatrixXd B = MatrixXd::Random(k, 2);
|
||||
MatrixXd C = A * B;
|
||||
MatrixXd Cref = MatrixXd::Zero(s, 2);
|
||||
for (int i = 0; i < s; ++i)
|
||||
for (int j = 0; j < 2; ++j)
|
||||
for (int kk = 0; kk < k; ++kk) Cref(i, j) += A(i, kk) * B(kk, j);
|
||||
VERIFY_IS_APPROX(C, Cref);
|
||||
}
|
||||
// Wide result: 2 x k * k x s (2-row GEMM)
|
||||
{
|
||||
MatrixXd A = MatrixXd::Random(2, k);
|
||||
MatrixXd B = MatrixXd::Random(k, s);
|
||||
MatrixXd C = A * B;
|
||||
MatrixXd Cref = MatrixXd::Zero(2, s);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
for (int j = 0; j < s; ++j)
|
||||
for (int kk = 0; kk < k; ++kk) Cref(i, j) += A(i, kk) * B(kk, j);
|
||||
VERIFY_IS_APPROX(C, Cref);
|
||||
}
|
||||
// GEMV: s x k * k x 1
|
||||
{
|
||||
MatrixXd A = MatrixXd::Random(s, k);
|
||||
VectorXd x = VectorXd::Random(k);
|
||||
VectorXd y = A * x;
|
||||
VectorXd yref = VectorXd::Zero(s);
|
||||
for (int i = 0; i < s; ++i)
|
||||
for (int kk = 0; kk < k; ++kk) yref(i) += A(i, kk) * x(kk);
|
||||
VERIFY_IS_APPROX(y, yref);
|
||||
}
|
||||
// Vec-mat: 1 x k * k x s
|
||||
{
|
||||
RowVectorXd v = RowVectorXd::Random(k);
|
||||
MatrixXd B = MatrixXd::Random(k, s);
|
||||
RowVectorXd r = v * B;
|
||||
RowVectorXd rref = RowVectorXd::Zero(s);
|
||||
for (int j = 0; j < s; ++j)
|
||||
for (int kk = 0; kk < k; ++kk) rref(j) += v(kk) * B(kk, j);
|
||||
VERIFY_IS_APPROX(r, rref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int>
|
||||
void bug_1622() {
|
||||
typedef Matrix<double, 2, -1, 0, 2, -1> Mat2X;
|
||||
@@ -193,11 +346,16 @@ EIGEN_DECLARE_TEST(product_large) {
|
||||
internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
CALL_SUBTEST_11(product(Matrix<bfloat16, Dynamic, Dynamic, RowMajor>(
|
||||
internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
CALL_SUBTEST_12(product(Matrix<Eigen::half, Dynamic, Dynamic>(internal::random<int>(1, EIGEN_TEST_MAX_SIZE),
|
||||
internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
}
|
||||
|
||||
CALL_SUBTEST_6(product_large_regressions<0>());
|
||||
CALL_SUBTEST_6(bug_gemv_rowmajor_large_stride<0>());
|
||||
CALL_SUBTEST_6(bug_gemv_run_small_cols<0>());
|
||||
CALL_SUBTEST_6(gemv_small_cols_systematic<0>());
|
||||
CALL_SUBTEST_6(gemv_rowmajor_large_stride_varied_rows<0>());
|
||||
CALL_SUBTEST_6(product_extreme_aspect_ratios<0>());
|
||||
|
||||
// Regression test for bug 714:
|
||||
#if defined EIGEN_HAS_OPENMP
|
||||
|
||||
Reference in New Issue
Block a user