Я использую EIGEN для оптимизации и функций с разреженной матрицей. Все «работает» хорошо, за исключением некоторых случаев, и я не могу понять этот случай.EIGEN: Малое умножение матрицы, не создающее обрезанный результат
Вот вещь:
Matrix A
2 0 0
0 2 0
0 0 2
Matrix B
6 3
0 1
2 8
Result
12 6
0 2
4 16
Как вы можете видеть, что это правильный результат, и я всегда иметь правильный результат.
Проблема заключается в значениях, которые считаются «Non Zero». В этом случае:
SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = A*B;
result.pruned();
cout << result.nonZeros();
Результат nonZeros()
составляет 5, что является «нормальным» случай, так как результат получил только 5 не равен нулю значения. Теперь давайте рассмотрим этот код:
SparseMatrix<int, RowMajor> A;
SparseMatrix<int, RowMajor> B;
//Parsing and initializing matrix
SparseMatrix<int, RowMajor> result = (A*B).pruned();
cout << result.nonZeros();
Результат nonZeros()
равно 6. Я не понимаю, почему это синтаксис доступен на the documentation.
А теперь самое странное, что на очень большой матрицы result = A*B; result.pruned()
иногда и экономить 0 в ноль, но меньше, чем если бы я использовал (A*B).pruned();
У меня три вопроса:
- Почему
result = (A*B).pruned()
иresult=A*B;result.pruned();
дает разные результаты относительно значений nonZero (а не эффективный результат, который является правильным в обоих случаях)? - Почему значения 0 из продукта иногда не считаются нулевыми значениями?
- У вас такой же результат, как у меня?
Я использую Visual Studio Professional 2013 и Eigen 3.3.2, используя режим DEBUG и предназначенный для WIN32.
Благодарим за помощь.
EDIT: Контрольный показатель разреженного умножения с VS2013, режим DEBUG/Release для W32 (с набором инструкций SSE2 или без него, одинаковые результаты в обоих случаях); результат всегда правильный, поэтому я не вставляю его здесь, он не приносит никакой информации.С:
1 = SparseMatrix<int, RowMajor> resultA = A*B;
2 = SparseMatrix<int, RowMajor> resultB = (A*B);resultB.pruned();
3 = SparseMatrix<int, RowMajor> resultC = (A*B).pruned();
Случай 1
Matrix A
2 0 0
0 2 0
0 0 2
Matrix B
5 3
0 1
2 8
Ожидаемое значение = 5
1 = 5
2 = 5
3 = 6
Случай 2 матрицы являются слишком большими, here является файл
Ожидаемое значение = 0
1 = 1444
2 = 1444
3 = 0
Как вы можете видеть, в зависимости как от входа и, как я звоню функции, результат оптимизируется или нет, и ни один из 1, 2 или 3 работает в каждом конкретном случае.
EDIT²: Проблема устранена решением ggael (спасибо).
Я просто изменил флаг компилятора на набор инструкций SSE2 и по-прежнему считал 0 значениями нуля. Что вы имеете в виду, убивая дополнительную точность FPU? Написание чего-то вроде конвертера? Я сделал тест, и, следуя результатам, я не уверен, что это проблема точности, потому что в зависимости от того, какой порядок вы вызываете, результаты разные. Я собираюсь добавить это в первый пост. – Spazz
Вы правы. Проблема исправлена в 3.3 и ветви девела. – ggael