私はいくつかの行列計算を行うために固有ライブラリを使用していました。私は長い行列を定義しなければなりません(実際にはそれほど大きくなく、ちょうど300x300)、各要素は長い複雑な指数表現で構成されています。 C++:-O2最適化で膨大な量の式のコンパイルに失敗しましたか?
は私が何を意味するかの印象を与えるために、私は窓にmingwの-W64を使用しています#include <iostream>
#include <complex>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
typedef std::complex<double> cd;
MatrixXcd h(300,300);
double kx,ky;
kx=1.;
ky=1.;
h.setZero(300,300);
h(0,0)=cd(6.942755,0.) + 0.043986/exp(cd(0,1)*(0. - 2.0238820899708214*kx - 7.55323078829979*ky)) - 0.010802/exp(cd(0,1)*(0. + 5.529348698328969*kx - 5.529348698328969*ky)) + 0.043986/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky)) + 0.043986/exp(cd(0,1)*(0. + 7.55323078829979*kx + 2.0238820899708214*ky)) - 0.010802/exp(cd(0,1)*(0. - 5.529348698328969*kx + 5.529348698328969*ky)) + 0.043986/exp(cd(0,1)*(0. + 2.0238820899708214*kx + 7.55323078829979*ky));
h(0,2)=cd(0.,0.) + 0.095916/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky)) - 0.131689/exp(cd(0,1)*(0. + 7.55323078829979*kx + 2.0238820899708214*ky));
h(0,3)=cd(-0.10825,0.) - 0.011519/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky));
...
...//6000 more lines omitted here
}
私の行列定義のごく一部をコピーし、コンパイラは罰金を設定しました。しかし、上記のコードを
g++ -O2 code.cpp
とコンパイルすると、コンパイルはポップアップダイアログで失敗します!
と私は慎重に、タスクマネージャを見れば、コンパイルは約1GBのメモリ使用量で停止。
しかし、-O0
オプションを使用してコードを再度コンパイルすると、すべての最適化が無効になります。メモリ使用量が2GBに近いピークに達しても、コンパイルは成功しました。 エラーはメモリが原因ではありません。
さらに、この動作は、Eigen
ライブラリとは関係がないことを確認できます。私はEigen
を使用し、同じ変数に代入すべてを置き換える、この
#include <iostream>
#include <complex>
int main()
{
typedef std::complex<double> cd;
cd tmp;
double kx,ky;
kx=1.;
ky=1.;
tmp=cd(6.942755,0.) + 0.043986/exp(cd(0,1)*(0. - 2.0238820899708214*kx - 7.55323078829979*ky)) - 0.010802/exp(cd(0,1)*(0. + 5.529348698328969*kx - 5.529348698328969*ky)) + 0.043986/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky)) + 0.043986/exp(cd(0,1)*(0. + 7.55323078829979*kx + 2.0238820899708214*ky)) - 0.010802/exp(cd(0,1)*(0. - 5.529348698328969*kx + 5.529348698328969*ky)) + 0.043986/exp(cd(0,1)*(0. + 2.0238820899708214*kx + 7.55323078829979*ky));
tmp=cd(0.,0.) + 0.095916/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky)) - 0.131689/exp(cd(0,1)*(0. + 7.55323078829979*kx + 2.0238820899708214*ky));
tmp=cd(-0.10825,0.) - 0.011519/exp(cd(0,1)*(0. - 7.55323078829979*kx - 2.0238820899708214*ky));
... //6000 more lines omitted
}
のようにコンパイルも-O2
オプションのために失敗していない場合でも。
また、問題はmingwコンパイラに限定されません。私はまた、インテルの並列スタジオicl.exeを試しました。状況はさらに悪く、コンパイルには30分以上かかり、それが繰り返し行われているように見えますが、私はそれが完了するのを待つ忍耐がなく、おそらく最後にも失敗する可能性があります。
だから私の質問は、-O2
でコンパイルに失敗した原因ですか? -O2
のコードを作成するにはどうすればいいですか?また、多くの表現があるにもかかわらず、それらは単純に要素exp
で構成されているので、なぜコンパイルに時間とメモリがかかるのですか?コンパイルを高速化するためのトリックですか?
更新
マルク・Glisseの提案によると、私は次のことを実行します。 -O1
が動作しますが、コードが科学計算目的のため、少なくともO2は必要です。スピードは重要です。
R:\>g++ -O1 -ftime-report eigen.cpp
Execution times (seconds)
phase setup : 0.01 (0%) usr 1540 kB (0%) ggc
phase parsing : 6.06 (5%) usr 412774 kB (25%) ggc
phase lang. deferred : 0.18 (0%) usr 6491 kB (0%) ggc
phase opt and generate : 122.65 (95%) usr 1203926 kB (74%) ggc
|name lookup : 0.61 (0%) usr 39968 kB (2%) ggc
|overload resolution : 2.18 (2%) usr 151685 kB (9%) ggc
garbage collection : 1.48 (1%) usr 0 kB (0%) ggc
callgraph construction : 0.65 (1%) usr 28545 kB (2%) ggc
callgraph optimization : 0.41 (0%) usr 6 kB (0%) ggc
ipa dead code removal : 0.02 (0%) usr 0 kB (0%) ggc
ipa inlining heuristics : 0.58 (0%) usr 6172 kB (0%) ggc
ipa reference : 0.02 (0%) usr 0 kB (0%) ggc
ipa profile : 0.11 (0%) usr 0 kB (0%) ggc
ipa pure const : 0.20 (0%) usr 0 kB (0%) ggc
cfg cleanup : 0.04 (0%) usr 0 kB (0%) ggc
trivially dead code : 0.05 (0%) usr 0 kB (0%) ggc
df scan insns : 0.09 (0%) usr 0 kB (0%) ggc
df multiple defs : 0.03 (0%) usr 0 kB (0%) ggc
df live regs : 0.13 (0%) usr 0 kB (0%) ggc
df live&initialized regs: 0.04 (0%) usr 0 kB (0%) ggc
df reg dead/unused notes: 0.17 (0%) usr 2440 kB (0%) ggc
register information : 0.01 (0%) usr 0 kB (0%) ggc
alias analysis : 0.05 (0%) usr 1546 kB (0%) ggc
alias stmt walking : 27.43 (21%) usr 19006 kB (1%) ggc
rebuild jump labels : 0.03 (0%) usr 0 kB (0%) ggc
preprocessing : 0.63 (0%) usr 8732 kB (1%) ggc
parser (global) : 0.30 (0%) usr 80513 kB (5%) ggc
parser struct body : 0.36 (0%) usr 20184 kB (1%) ggc
parser enumerator list : 0.03 (0%) usr 1004 kB (0%) ggc
parser function body : 3.52 (3%) usr 253532 kB (16%) ggc
parser inl. func. body : 0.16 (0%) usr 6243 kB (0%) ggc
parser inl. meth. body : 0.24 (0%) usr 12261 kB (1%) ggc
template instantiation : 0.75 (1%) usr 36791 kB (2%) ggc
early inlining heuristics: 0.74 (1%) usr 78738 kB (5%) ggc
inline parameters : 0.60 (0%) usr 3273 kB (0%) ggc
integration : 34.96 (27%) usr 421223 kB (26%) ggc
tree gimplify : 0.93 (1%) usr 78917 kB (5%) ggc
tree eh : 1.81 (1%) usr 147729 kB (9%) ggc
tree CFG construction : 0.26 (0%) usr 47487 kB (3%) ggc
tree CFG cleanup : 0.92 (1%) usr 0 kB (0%) ggc
tree copy propagation : 0.03 (0%) usr 0 kB (0%) ggc
tree PTA : 1.80 (1%) usr 167 kB (0%) ggc
tree PHI insertion : 0.07 (0%) usr 519 kB (0%) ggc
tree SSA rewrite : 1.63 (1%) usr 97983 kB (6%) ggc
tree SSA other : 0.13 (0%) usr 17 kB (0%) ggc
tree SSA incremental : 28.75 (22%) usr 5 kB (0%) ggc
tree operand scan : 2.13 (2%) usr 65917 kB (4%) ggc
dominator optimization : 0.08 (0%) usr 2043 kB (0%) ggc
tree SRA : 2.65 (2%) usr 56210 kB (3%) ggc
tree CCP : 2.42 (2%) usr 37765 kB (2%) ggc
tree split crit edges : 0.11 (0%) usr 2953 kB (0%) ggc
tree reassociation : 0.04 (0%) usr 0 kB (0%) ggc
tree FRE : 3.35 (3%) usr 35524 kB (2%) ggc
tree code sinking : 0.01 (0%) usr 0 kB (0%) ggc
tree linearize phis : 0.01 (0%) usr 6 kB (0%) ggc
tree backward propagate : 0.02 (0%) usr 0 kB (0%) ggc
tree forward propagate : 0.38 (0%) usr 8 kB (0%) ggc
tree conservative DCE : 0.13 (0%) usr 1 kB (0%) ggc
tree aggressive DCE : 0.33 (0%) usr 2 kB (0%) ggc
tree DSE : 0.45 (0%) usr 4 kB (0%) ggc
tree SSA uncprop : 0.01 (0%) usr 0 kB (0%) ggc
dominance frontiers : 0.06 (0%) usr 0 kB (0%) ggc
dominance computation : 0.65 (1%) usr 0 kB (0%) ggc
out of ssa : 0.09 (0%) usr 1 kB (0%) ggc
expand vars : 0.02 (0%) usr 765 kB (0%) ggc
expand : 0.13 (0%) usr 13796 kB (1%) ggc
post expand cleanups : 0.03 (0%) usr 2868 kB (0%) ggc
forward prop : 0.08 (0%) usr 156 kB (0%) ggc
CSE : 0.08 (0%) usr 304 kB (0%) ggc
dead code elimination : 0.03 (0%) usr 0 kB (0%) ggc
dead store elim1 : 0.09 (0%) usr 763 kB (0%) ggc
dead store elim2 : 0.08 (0%) usr 613 kB (0%) ggc
loop init : 0.15 (0%) usr 65 kB (0%) ggc
branch prediction : 0.12 (0%) usr 19 kB (0%) ggc
combiner : 0.10 (0%) usr 216 kB (0%) ggc
if-conversion : 0.01 (0%) usr 0 kB (0%) ggc
integrated RA : 0.43 (0%) usr 9659 kB (1%) ggc
LRA non-specific : 0.26 (0%) usr 305 kB (0%) ggc
LRA virtuals elimination: 0.03 (0%) usr 304 kB (0%) ggc
LRA create live ranges : 0.03 (0%) usr 152 kB (0%) ggc
LRA hard reg assignment : 0.02 (0%) usr 0 kB (0%) ggc
reload CSE regs : 0.19 (0%) usr 916 kB (0%) ggc
thread pro- & epilogue : 0.04 (0%) usr 14 kB (0%) ggc
hard reg cprop : 0.07 (0%) usr 0 kB (0%) ggc
shorten branches : 0.08 (0%) usr 0 kB (0%) ggc
final : 0.16 (0%) usr 279 kB (0%) ggc
initialize rtl : 0.01 (0%) usr 12 kB (0%) ggc
rest of compilation : 0.31 (0%) usr 879 kB (0%) ggc
remove unused locals : 2.24 (2%) usr 0 kB (0%) ggc
address taken : 1.00 (1%) usr 37564 kB (2%) ggc
rebuild frequencies : 0.02 (0%) usr 0 kB (0%) ggc
TOTAL : 128.90 1624743 kB
中間のサイズの例を-ftime-reportでコンパイルして、何時間がかかるかを調べることができます。しかし、大規模な自動生成ソースファイル(-O1を試したかどうかは言及していません)では、-O1に固執することが推奨されます。 –
こんにちは、@MarcGlisseご意見ありがとうございます。私は自分の投稿を更新しました。 '-O1'は動作しますが、' -O2'が必要です – user15964