• 締切済み

行列計算の速度

行列計算の速度 今、スパース行列計算のプログラミングをしているのですが、Cで作成していて、計算速度について考慮しています。同じような計算をmatlabでさせてみたら、matlabでの行列計算は圧倒的に速かったので、matlabを使う事を考えてます。行列計算を得意とするmatlabなのですが、matlabはCを使っているので、Cでのプログラミングをあきらめるべきなのか考えています。 Cもmatlabも良い点、悪い点はあると思いますが、何か参考になるアドバイスがあればいいなと思って、投稿させてもらいました。お願いします。

みんなの回答

  • Interest
  • ベストアンサー率31% (207/659)
回答No.4

C言語だから遅いというのではなくて、大規模な疎行列にガウスの消去法を使ったから遅いのだと思います。 10000×10000の行列を作るために malloc でメモリを確保したそうですが、ザックリ 762MBですか。いまどきのPCだとRAMをGB単位で積むのが当たり前だから気にしないのでしょうか。RAMが少なければスワップが大量に発生しそうな気がします。 Matlabはこのような手法で疎行列の演算を高速化しているようですね。(学生さんの卒論なので、どこまで正しいか保証はできませんが。) http://dspace.wul.waseda.ac.jp/dspace/bitstream/2065/671/1/1g01p100.pdf 反復法について。 http://sstweb.ee.ous.ac.jp/lecture/ee/NumericalCalculations/ncd20061204.pdf 数値計算法をキーワードにして探せば、大規模な連立一次方程式の解法が見つかるんじゃないでしょうか。 (自分で作るとバグも作っちゃうから、Matlabを使うというのも一つの手だと思います。)

ibuneko
質問者

お礼

直接法と反復法の両方試しましたが、やはり直接法が早かったので、それでプログラミングをしてみました。 計算速度を早くするためにいくつか手段があるみたいなので、試してみたいと思います。 回答と、参考資料のリンクありがとうございました。

回答No.3

>Cもmatlabも良い点、悪い点はあると思いますが、何か参考になるアドバイスがあればいいなと思って、投稿させてもらいました。 参考になるかどうかは判りませんが、 一般的にFPUを使用した浮動小数点の演算はC言語を含むあらゆる高級言語より、アセンブラの方が圧倒的に高速実行が可能です。それは以下の理由によります。 ・並列処理の記述が高級言語では不可能 ・関数の引数のレジスタ渡しができない ・FPUの特殊機能が高級言語では記述不可能 Intelのx86のプロセッサで説明しますと (1)並列処理の問題 高級言語で実現不可能なのは以下の並列化処理。 ・FPUはパイプラインで動作しており、そのパイプラインに空白を作らないようにプログラミングをする。 ・FPUとALUは独立して動作可能(バスは共通)なのでFPUの実行中にALUを使って演算を並列化させる。 FPUとALUを同時に動作させる考え方は昔から存在していたのですが、内蔵キャッシュがなくて外部バスにFPUがブル下がっていた頃はあまり効果がなかったのです。今はキャッシュにデータが入っていれば1クロックでアクセスできますから効果が大きいのです。 (2)関数の引数の問題 C言語では関数に値を渡す場合にスタックを利用するのが一般的です。しかし浮動小数点の演算ではFPUのレジスタを使用するため、以下の問題があります。 ・関数の呼び出し側ではFPUのレジスタからデータを取り出し、スタックにプッシュする。 ・関数を実行する側ではスタックから値を取り出し、FPUにロードする。 という非常に無駄な作業を繰り返すことになります。引数が多い場合にはスタックを使用するしかありませんが4個程度なら「FPUのレジスタ渡し」が圧倒的に高速です。この技法は30年前から存在していました。 (3)FPUの特殊機能 IntelのプロセッサーではMMXやSSEを指します。SSEを使用する場合にはC言語では記述の方法がないのでアセンブラでプログラミングをします。 具体的には、IntelのHPから『Intel Architecture Software Developer's Manual』を参照してみてください。 アセンブラで効率がよく実行速度が速いプログラムを書くのは職人芸です(^^)ノ ちなみに私はmatlabではなくてscilabを使用しています。ソースコードの提供も含めて無料なので^^

ibuneko
質問者

お礼

scilabでの計算速度も比較してみます。ありがとうございます。専門的な情報を記載していただき、学ぶことがたくさんありました。 プログラミングスキルに関してはまだまだペーペーな域なので、がんばります。

  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.2

まったくの個人的な見解ですが。 経済的に余裕があるならmatlabを利用し続けるのは有利と思います。 私も今までに、アッセンブラ、コンパイラ言語、インタプリタなど かなりの数を扱いましたが、数値解析専用のインタプリタはラクですね。 ただ、数値解析を行う前後の処理で大掛かりなことを行なおうとしたら 実現方法に悩むかもしれません。 最近はプログラミングをしていませんが、行列計算で速度を求めるならば スーパーコンピュータもやった経験から、マルチコア演算、GPU利用の 演算に非常に興味があります。 matlibがそれらに対応してくれたら話は簡単ですが、対応してくれない なら自分でやるしか無く、C/C++は手放せないのかな、とも思います。 スーパーコンピュータにはその性能を引き出すべく、専用の言語がありま すので、GPU演算もライブラリとかが世に出ているのかも知れませんけど。

ibuneko
質問者

お礼

そうですね、お金をかけてもいいくらいの速さなら、教授に頼み込めるので、教育のためなら理解してくれると思うので、matlabの使うのを聞いてみます。 ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

普通に考えて, Matlab の方が圧倒的に「遅い」ことはほぼありえないよなぁ. とりあえず ・「スパース」というのがどのくらい「スパース」なのか ・どのような計算をしたいのか ・あなたのプログラムでは「スパース行列」をどのように記憶しているのか ・あなたのプログラミングスキルはどのくらいなのか ・そもそもあなたの目的はなんなのか などによって「アドバイス」が変わる可能性があります. 特に最後の点は重要で, たとえば「行列の計算をするプログラムをプリミティブなレベルから組む」ことを目的とするのであれば Matlab はそもそも問題外だし, 逆に「計算ができればいいだけであって『プログラムがくめるようになる』ことは歯牙にもかけていない」というなら Matlab で突き進んでもまったく問題ない. というわけで, あなたの目的意識はどこにあるんでしょうか?

ibuneko
質問者

補足

最大で10000x10000のスパースになり、それぞれのrowには2~5個の非ゼロ要素がはいり、diagonalの要素はすべてpositive、off-diagonalの要素はnegativeになります。 連立方程式、Ax=b、のxを求める手段として、直接法のGaussian eliminationを使う事を考えています(diagonal dominanceになるので)。 プログラミング自体はここ2年ぐらいの経験で、この行列計算をCで作っています。行列の大きさは様々になるので、mallocして領域を確保してます。あまり、プログラミングの経験がすくないので、専門的なことはまだ知らないことが多いです。 目的としては、上記にもありますように、連立方程式の解、xを求めることです。それで、Cとmatlabでしたら、どちらがいいのかとなり、質問を投稿しました。

関連するQ&A

  • Sparse matrix 計算

    Sparse matrix 計算 Ax=Bの行列計算で、行列は最大で10000*10000になります。Cでガウスの消去法を使ってコードが書いたのですが、計算がかなり遅いので,何かいいライブラリがないかと思って探しているのですが、CLAPACKはsparse matrixに向いてないと書いてあり、どうすればいいのか考えているところです。BLASだけでも計算時間は早くなるのでしょうか?sparse matrixの解を求めるソフトウェアは出てるのですが,有料のものもあるのですが、無料のものでできるのであればそちらを使いたいと思ってます。アドバイスお願いします。

  • Javascriptでの行列計算

    Javascriptでの行列計算 Javascriptで行列計算のプログラミングの作成を考えています。 例として、 G*v=I が成り立つと仮定し、vのベクターを求めたいのです。 Gはn*nの行列で、Iはn*1のベクターです。nは最大で10000になります。一次連立方程式を使ってvベクターを求めることは可能ですか?効率のいいアルゴリズムはありますでしょうか?消去法を使えばいいのかなと考えていますが,行列計算に関してあまり知識がないので、ここで質問させていただきました。

  • 非正方行列の行列式をC言語で計算したいのですが。

    非正方行列の行列式を求めたいのですがどのような式になるのでしょうか? また、これをC言語で作成しなければなりません。 プログラミングはほぼ初心者なので、回答者様の手間にならない程度で優しく回答していただければと思います。 宜しくお願いします。

  • cのプログラミングで虚数を含む行列の計算の考え方がわかりません

    cのプログラミングで行列の積を計算するものまではできたのですが、その行列の中に虚数を含むものの考え方がよくわかりません。 たとえば  ia b  c id    (a,b,c,dが実数、iが虚数) というような行列があるときこれと同じものの積を何回かするプログラムを作るとき、虚数をどのような対処をすればいいのでしょうか? よろしくお願いします。

  • 行列の計算の進め方

    行列P(a,b,c,d)(順に左上,右上,左下,右下の成分です)が P^2-dP=P^(-1)…(1) および ad-bc=1…(2) を満たしている。このときa=-1を示せ。ただしa,b,c,dはいずれも実数である。 という問題なんですが、まず逆行列が嫌なので(1)に両辺Pをかけて逆行列を消し、またハミルトンケーリーで今作った式の次数下げをどんどんやっていきます。そうすると、 {a(a+d)-1}P=(a+1)E という式が出てくると思うのですが、ここで場合分けに入ると、 a(a+d)-1=0 の場合はa=-1と定まるのですが、 a(a+d)-1≠0 の場合に、PはEの実数倍にならないということが言えませんので((2)よりdetP=1)P=kEとしてハミルトンケーリーの式に代入することになると思います。ところ が代入した後に{k^2-(a+d)k+1}E=0となり、kの2次方程式が表れますが、これ以上進めません。 どこか見落としているだけかもしれませんが... 解答では素直に逆行列を求めてから成分を比較して、途中背理法を使うことによってa=-1と示していました。もちろん僕のやり方をするなら後者のほうも調べないといけませんから、このままでは点数になりません。 お聞きしたいことは2点あります。 一つ目は僕が進めなかったところから進めるのか。 二つ目はどういうときに成分計算に入ろうと考えるのか。 特に二つ目は、行列は成分計算が面倒になるからなるべく行列式でもちこみたいと教わっていたので、どうも成分計算に入る決意が出来ません。特に今回のようにもう少しで出来るのでないかと思うようなところまでくるとなおさら「いまさら成分なんか計算してたら時間が無くなってしまう!」と考えてしまいます。それは問題量や経験の差かもしれませんが、何かアドバイスあればよろしくお願いします!

  • matlabで迷路作成

    迷路作成のプログラミングをmatlabで作りたいと思っています。 作るアルゴリズムとしましては、壁伸ばし法で 『初めに大きな一部屋の迷路を用意し、乱数を用いて壁の一点を選び、自分自身とぶつからないように壁を伸ばしていく。伸ばせなくなったら、別の一点を選び、同じ操作を繰り返す。壁を作る場所がなくなったら終わる。壁を伸ばす方向は乱数で決める。』です。 一部屋は5×5の行列で、乱数は一様乱数を成分とする行列を使って、プログラミングしたいのですが、matlabの使い方がいまいち分からないため、それをどこにどう書けばいいかわかりません。 matlabに詳しい方、このアルゴリズムをプログラミングできる方は、やり方を詳しく教えていただけないでしょうか?よろしくお願いします。

  • MATLABの行列を変換したいのですが

    行列の計算がMATLABで実行されて出てきた値Kfb Kfb=[-0.3162 -7.6248 -4.4566 -1.2231] を次のようにデータを抽出したいのですが、上手くいきません。 どのように行えば可能になるのか教えていただけると幸いです。 Kfb1=[-0.3162 -7.6248] Kfb2=[-4.4566 -1.2231] また、C言語のように割り込みを入れることは可能なのでしょうか? よろしくお願いします。

  • CとFORTRANの計算速度はどちらが速いですか?

    マシンスペックは同じとして、OSはUNIXであった場合、科学技術計算(微分方程式を解いたり、行列を対角化したり。。。)の計算速度はどちらが速いですか? 普通、科学計算というとFORTRANを使っていますが、これはライブラリの遺産が多いからだと思いますが、実際のところFORTRANとCではどちらが計算速度が速いのでしょうか。

  • MATLABとC++

    こんにちわ。資料を参考にしつつMATLABからC言語へ変換する作業をしているのですが、どちらに関しても初心者レベルで遅々としてはかどりません…。 分からないことの一つとして、MATLABは行列計算がしやすいがC言語はそうではないということからなのですが、MATLABで A = zeros(10,20,30) というのは次元10×20×30をもつゼロ行列 ということは分かったのですが、これは 数学で習う行列、2×2 や3×3など二次元な数字の並びを、三次元にまで拡張した表し方ということでしょうか?? また、上の式をC言語で書き表すとすると どのように書き表せるのでしょうか?どなたか分かるかた 教えていただければと思います。

  • 行列

    行列A=(a b)で表される1次変換fによって点(1,2)が点(5,5)に移りfの     (c d) 逆変換(f^(-1))によって点(2,4)が点(0,1)に移るときcの値を求める問題です。 解くと a+2b=5 c+2d=5 逆数より d-2b=0 -2c+4a=ad-bc からどのように計算をすれば求められるか教えてください。

専門家に質問してみよう