2017-02-09 5 views
0

私はスパース行列の最適化と関数に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 

あなたが見ることができるように、これは正しい結果であり、私は常に正しい結果を抱えています。

問題は「非ゼロ」と考えられる値です。この場合:

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()の結果は、これはthe documentationで利用可能な構文である理由を私は理解していない6です。

そして今、奇妙な部分はそれが上の非常に大きな行列result = A*B; result.pruned()では時々、ゼロでないとして0を保存しているが、私は(A*B).pruned();

を使用未満ならば、私は3つの質問だ:

  • はなぜresult = (A*B).pruned()であり、 result=A*B;result.pruned();は、ゼロ以外の値に関して異なる結果をもたらします(有効な結果ではありません。どちらの場合もそうです)。
  • 製品の0値がゼロ値と見なされないのはなぜですか?
  • あなたは私と同じ結果を出していますか?

私はVisual Studio Professional 2013とEigen 3.3.2を使用しています。DEBUGモードとWIN32をターゲットにしています。

ありがとうございました。

EDIT: VS2013による疎乗算のベンチマーク、W32のDEBUG /リリースモード(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

2 = 1444

3 = 0

あなたが見ることができるように、入力と私は関数を呼んでいる途中で両方を依存し、結果は最適化されたかどうか、そしてどれも1、2または3のいずれの場合にも取り組んでいます。

EDIT²:問題はggaelソリューションで修正されました(感謝)。

答えて

1

私の以前の回答(下記)は間違っていました。問題はthereで修正されました。

これは、win32を対象としているため、FPUレジスタの拡張精度の古典的な問題である が発生しているためです。 デフォルトでは、prunedは、0に厳密に等しいエントリを削除しますが、FPUでは を削除します。 がレジスタからメモリにコピーされた後でのみ、ゼロ以外の値がゼロになる可能性があります。コンパイラフラグ をSSE2命令セットのターゲットに更新するか、余分なFPU の精度で終了してください。

+0

私はコンパイラフラグをSSE2命令セットに変更しましたが、依然として0をゼロ値とみなしました。余分なFPUの精度を無くしてどういう意味ですか?コンバータのようなものを書いていますか?私はベンチマークを行い、その結果に続いて、関数を呼び出す順番によっては結果が異なるため、精度の問題であるとは確信できません。私は最初の投稿にこれを追加します。 – Spazz

+0

あなたは正しいです。 3.3およびdevelブランチで修正された問題 – ggael

関連する問題