VC++ 高速演算コードの沢山の変数の宣言方法

このQ&Aのポイント
  • VC++ 高速演算コードの沢山の変数を効果的に宣言する方法とは?
  • FortranのコードをVC++2010に移植する際、変数宣言の最適な方法について悩んでいます。サブルーチン化を検討しているため、大量の変数を効率的に扱う方法が知りたいです。
  • VC++ 高速演算コードの最適な変数宣言方法を教えてください。プログラムの高速化を優先するために、変数の宣言と参照方法についての効果的なアドバイスをお願いします。
回答を見る
  • ベストアンサー

VC++ 高速演算コードの沢山の変数の宣言方法

 【VC++ 高速演算コードの沢山の変数を、どのように宣言すべきでしょうか?】  今日は、質問させていただきます。 もしお詳しい方がいらっしゃいましたら、 どうぞよろしくお願いいたします。  Fortranのコード(歴10年程度)を、VC++2010(歴3ヶ月程度)になおそうとしております。  ボリュームのある数値解析のコード(3000行程度ございます)を、見やすくするために、 数百行ずつでサブルーチン化したい次第でございます。    例)int main(){                ←変数の宣言場所         definition()         calculation1()         calculation2()         calculation3()         conclusion()      }  しかしmainの最初(上記「変数の宣言場所」)にまとめて宣言しております変数が200個以上ございまして、これらの半分近くを各々のサブルーチンに毎回渡そうといたしますと、引数の量が膨大になってしまいますし、 またサブルーチン内で何か追記する度に引数を追加・削除せねばなりませんので、出来れば避けたい次第でございます。  そこで「全てPublicで宣言してしまおうかな?」などと考えて検索しておりましたが、「できる限りPublic変数を宣言すべきでない」といったような記事もございましたので、悩んでおります。 (Fortran環境下では、ヘッダファイル内のPublic変数を、全サブルーチンで毎回呼び出しておりましたが、それも良くないのかな、と迷っております。)  あと、上記のような宣言方法や参照方法が計算速度に影響するものなのかどうか分からないのでございますが、 平均で10日間程度まわし続けるプログラムになりますので、出来る限り「高速化」を優先したい次第でございます。  変なご質問かもしれませんので大変恐縮でございますが、 是非アドバイスいただけないでしょうか。(書物やサイトをご紹介いただけるのでも結構でございます)  何卒よろしくお願いいたします。

  • MKT_
  • お礼率99% (329/330)

質問者が選んだベストアンサー

  • ベストアンサー
  • Ogre7077
  • ベストアンサー率65% (170/258)
回答No.3

C++ なので、単純に考えるならクラス化でしょうか 大量の変数はクラス内の private とし、 変数を操作する関数はクラス内の public とし、 main にてクラスのインスタンス生成/操作/削除を行います。 これにより以下が期待できます。 * 変数を隠蔽するカプセル化により、Public変数宣言でありがちな問題を回避できる * 同一インスタンスならば、関数はすべての変数を引数や宣言無しに参照・更新できる * クラス内の変数処理は機械語レベルで最適化されるので、高速化にも有利 以下サンプルです class ボリュームのある数値解析 { private:  int alpha; // 変数の宣言  int beta;  ...  int omega; public:  void definition(); // 関数の宣言  void calculation();  void conclusion(); } void ボリュームのある数値解析::definition(){  alpha = 1, beta = 2, ...; // クラス内のすべての変数が参照・更新可能 } void ボリュームのある数値解析::calculation(){  omega = alpha + beta + ...; } void ボリュームのある数値解析::conclusion(){  出力(omega); } int main(){  ボリュームのある数値解析 *obj;  obj = new ボリュームのある数値解析(); // 生成  obj->definition(); // 操作  obj->calculation();  obj->conclusion();  delete obj; // 削除 }

MKT_
質問者

お礼

 Ogre7077様  どうもありがとうございます!! サンプルを書いていただいたお陰で非常に分かりやすかったです。m(_ _)m >同一インスタンスならば、関数はすべての変数を引数や宣言無しに参照・更新できる >クラス内の変数処理は機械語レベルで最適化されるので、高速化にも有利  私では思いつかない内容でしたので、非常に興味がございます。^^ まずNo.1様からアドバイスいただいたようにコードを整理&見直してから、 更にOgre7077様にご提示いただいた内容に変更する事にいたします。 (時間がかかりそうでございますが。。。^^;)  ご親切にご閲覧・アドバイスいただきまして誠にありがとうございました!!!!m(_ _)m

その他の回答 (4)

  • ninoue
  • ベストアンサー率52% (1288/2437)
回答No.5

FORTRN、VC++共に今後もサポートされ続けられると思われますし、高速化の点ではFORTRANの方が充実したパッケージ等が揃っておりコンパイラもFORTRANの性能の方が上のようですし、主要部分はこれまで通りFORTRANのままでも良いのではないでしょうか。 入出力連携やディスプレイ表示(グラフ、平面、立体、アニメ、動画...)などの点でVC++が便利なのでしたら、mainはFORTRANのままで入出力部分等をVC++で処理する事も可能だと思われます。 "FORTRAN C++ 連携 OR インターフェイス" "FORTRAN C++ 連携 OR インターフェイス common" 等とサーチされたら色々な例が見つかります。 common blockを宣言し、FORTRAN, VC++の両プログラムから沢山の変数は共通にアクセス出来るのではないでしょうか。 FORTRAN内で使われていた沢山の変数は、宣言部分のみを書換えれば実行部分では殆どそのままでアクセス出来るのではと思われます。 それからご存じとは思いますが、二次元や三次元のデータアクセス等に当ってはFORTRANとVC++ではabc(i,j,k)をどの順番で(i,j,kのどれを一番内側のループにして)早く変化させるか、メモリ上でどの順番にデータが並んでいるか<==>キャッシュラインヒット率を上げるか等で、単純な書換えでは性能が反って悪化する場合もあるのではと思われます。 既に調べられているとは思いますが、次等いろいろと検討が必要のようです。 http://www.moonmile.net/blog/archives/3359 FortranのCOMMONブロックをC++から扱う http://www.xlsoft.com/jp/products/intel/compilers/fcw/12/ug/bldaps_for/common/bldaps_call_cproc.htm インテル@Fortran プログラムからの C プロシージャーの呼び出し http://docs.oracle.com/cd/E19957-01/806-4843/Cp11_cfort.html C と Fortran のインタフェース システム全体の事が解らずにピント外れの回答でしたら申しわけありません。

MKT_
質問者

お礼

ninoue 様  どうもありがとうございます!! >システム全体の事が解らずにピント外れの回答でしたら申しわけありません。  いえ非常に貴重なご意見でございます。ご親切にどうもありがとうございます。m(_ _)m >入出力連携やディスプレイ表示(グラフ、平面、立体、アニメ、動画...)などの点でVC++が便利なのでしたら、mainはFORTRANのままで入出力部分等をVC++で処理する事も可能だと思われます  はい、計算結果を一定の時間ステップ毎に可視化する必要がございました為、VS上でそのようなソフトを作ってみたかった次第でございます。 >common blockを宣言し、FORTRAN, VC++の両プログラムから沢山の変数は共通にアクセス出来るのではないでしょうか。  なんとそのような事が可能なのでございましたか(・o・)存じませんでした。 となりますと、こちらも選択肢に入りますね。迷います^^  自分で検索&勉強させていただきます!!この度はご親切に誠にありがとうございました!!!m(_ _)m

  • ki073
  • ベストアンサー率77% (491/634)
回答No.4

高速化に関してだけですが、 経験上、FORTRANが一番速いコードになることが多く、Cが注意深く書くとFORTRANと同程度、C++ではC++らしく書くとそれなりに遅くなります。 コードによって最適化が全然効かなかったりします。コンパイラの最適化性能にもよりますが、今時のコンパイラはどれでもそれなりに最適化してくれますので、基本的にはコード次第です。 >上記のような宣言方法や参照方法が計算速度に影響するものなのかどうか分からないのでございますが 関数をインライン展開すればほとんど影響しないと思います。それも時間がかかる多重ループの中だけ考慮すれば十分です。FORTRANは明示的インライン展開する機能はないはずですが、コンパイラのオプションに大概ありますのでそれを利用します。 高速化の基本は、プロファイラで時間のかかる部分を特定して、そこを中心に対策することです。数値計算の場合は僅かな部分がほとんどの計算時間を消費してる場合がほとんどです。そこをベクトル化や並列化ができるコードにすればかなり速くなります。(時間のかかる部分は多重ループになっていること多く一般的にベクトル化や並列化しやすい)。 それ以外のところはどのような(非効率?な)書き方をしてもほとんど影響しないということです。 ベクトル化や並列化ができれば、それをGPUで実行させるとさらに高速化が期待できます。 >平均で10日間程度まわし続けるプログラム 最適化のやりがいがありますね。GPUでうまくいけば一桁程度は速くなります。

MKT_
質問者

お礼

 ki073様  ご親切にどうもありがとうございます!! >経験上、FORTRANが一番速いコードになることが多く、Cが注意深く書くとFORTRANと同程度、C++ではC++らしく書くとそれなりに遅くなります。 Cを注意深く書くスキルを身につけるよう頑張ります(`_´)ゞ GPUも今勉強しております^^  プログラミングについては過去、誰かに教わったという経験がございませんで、初めからぶっつけでサンプルコードを引用したり、 自分で検証をひたすら繰り返してまいりました。そのため、今回いただけたようなアドバイスは非常に貴重であり、勉強になります。  どうもありがとうございました!!!m(_ _)m

  • f272
  • ベストアンサー率46% (7997/17097)
回答No.2

#1さんの言うことはもっとですが,とにかく > Fortranのコード(歴10年程度)を、VC++2010(歴3ヶ月程度)になおそうとしております。 ということであれば,プログラム構造をいじることなく,そのまま変換することを目指すほうがよいように思う。 そして,誤りなく変換されて動作が安定したら,それからモジュール分割とかいろいろと考えればいいのではないだろうか? 高速化を考えているのならfortranのままのほうがいいかもしれない。とにかく高速化のネックになっているところを特定することからはじめるべきでしょう。

MKT_
質問者

お礼

 f272様  どうもありがとうございます!! >高速化を考えているのならfortranのままのほうがいいかもしれない。  はい、説明が不足しておりまして大変失礼いたしました。定期的に画像出力するなどVSを使う必要が出てまいりました為、 (VisualStudio上でのコーディングが好きだという理由もあるのでございますが^^;)、VC++を選択したくなった次第でございます。 高速化のネックにつきましても見直してまいります!!(`_´)ゞ  どうもありがとうございました!!!m(_ _)m

回答No.1

基本的には、「各所で使い回すような変数が200個以上あるようなプログラムを分割するのはやめた方がいいです」ということになります。 あと、「行数が多いので、わかりやすくするために、一定の行数で分割する」という方針も、正しくないことの方が多いです。 分割は、「処理」とか「機能」の単位で行うべきかと思います。 という基本を押さえておいた上で。 まず、Publicな変数を多用すべきでないというのは、本来、「どこでその変数をいじっているかわららなくなるから、ある変数がおかしくなったときに、どこでおかしなことをしているのか、追いかけるのが大変だから」です。 そういう意味では、200個の変数があって、その多くが(半数近くが)あちこちで使い回されるということは、十分、「どこでその変数をいじっているのかわからない」状態です。 なので、この状態で、「Public をやめて、すべて引数で」と力んでみても、あまり効果はないです。 さらに、 > またサブルーチン内で何か追記する度に引数を追加・削除せねばなりませんので、 > 出来れば避けたい次第でございます。 というのも、本来は、あるはずのないことです。 モジュール分割には、「強度」と「結合度」という概念があります。 http://www.kogures.com/hitoshi/webtext/kj2-module/ モジュールを分割しているのに、たくさんの引数を渡す必要があるというのは、本来間違いです。 その関数の中でしか使わない情報を、関数の外に出さなくてもいいように、モジュールの分割をするのが正しいです。 普通は、main で大量の変数を宣言するというのは、間違った設計を示す兆候です。 その点を、考えてみるといいかと思います。 ただ、計算内容によっては、本当にたくさんの変数があちこちで必要になることもあるようです。 その場合、大量の変数が、すべて無関係に存在しているということはないと思います。 ある程度のまとまりのある変数は、「構造体」を使ってひとまとめにすると(そして、その構造体を引数に使うと)見かけ上、引数を少なくすることもできます。 また、データの持ち方を変更する場合でも、構造体レベルで変更すれば、関数の見かけは変わらないことが多いです(きちんと、機能的な分割ができている場合)

MKT_
質問者

お礼

 asano_nagi 様  どうもありがとうございます!m(_ _)m ひと通り試しておりご返信が遅くなりました。大変失礼いたしました。  すべてじっくり読ませていただきましたが、全て「なるほど」でございます。 >モジュール分割には、「強度」と「結合度」という概念があります。 存じませんでした。^^; あと自分のコードを見直しましたが、殆どの変数がどこでも書き換えられる事が出来るようになっております。 今回いただいたアドバイスを活かせるように まず、分割してあるサブルーチン群を全てメインに戻してみます。 →(Fortranのコードと計算結果を比較し一致することを確認いたします。) →「処理」とか「機能」の単位で行える部分のみ分割し、 →>関数の中でしか使わない情報を、関数の外に出さなくてもいいように、モジュールの分割をする を行ってみます。  この度はご親切に誠にありがとうございました!!m(_ _)m

関連するQ&A

  • Visual C++とVisual Fortranの変数を共用したい

    FORTRANで作成したサブルーチンを活用し、C++からコールする形でコードを再利用しようと考えています。 C++からFORTRANを呼び出すのはすぐに出来たのですが、データの引渡しで困っています。 FORTRAN側ではグローバルな変数を多数(100個以上)宣言しており、引数としては渡せないのでC++側でも同名の変数を宣言して共用し、データのアクセスをしようと目論んでいます。FORTRAN側のコードは極力触りたくありません。 しかし、FORTRANでexternに相当する宣言の仕方が分からず、うまく同じ領域を共用できるようになっていません。 具体的にどんなことをすれば良いのかご存知の方がいらっしゃいましたら、ぜひご教授願います。 宜しくお願いします。

  • 混合言語のデバッグ(VC++6.0,VF6.0)

    VCからFORTRANのサブルーチンを呼び出すプログラムを作ったのですが、FORTRANサブルーチンの変数がWATCHできなくて困ってます(DEBUG WINDOW→変数で表示されない)。どなたかアドバイスをお願いします。ちなみにサブルーチンの戻り値、参照値は正常です。

  • 変数宣言は、最初に全部列挙したほうがいいですか?

    100行ぐらいのスクリプトだと、10個ぐらい変数宣言しなければいけませんが、 最初にまとめて書くメリットを教えてください。 ※他人のコードを読んでいて、最初にすべての変数宣言があったら、最初に戻らないとわからなくなり、その時、その時に、変数宣言があったほうがいいかなと。 ※言語によって違ってきますが、例えばJAVASCRIPTだとグローバル関数とローカルの問題があります。そのようなことを踏まえて、ご経験、ご意見を教えてください。

  • Perlのmyのサブルーチンの内外での宣言の違い

    Perlでmyを使う場合、サブルーチンの内外での宣言の違いについて知りたいです。 私はよくある変数をそのプログラム内全体で使う時(カウントするだけの$iみたいなものや、DBのクエリなど)は、同じ変数名をサブルーチン内で毎回宣言するのが嫌(個人的に同じことを重複するプログラムが好きではないという主義)なので、サブルーチンの外でmyを宣言するのですが、myとかはサブルーチン外で宣言するとどんな問題が生じる可能性があるのでしょうか? また毎回サブルーチン内で宣言するのと外部で宣言するのではどういった時に問題になるのでしょうか?もちろんサブルーチンの外でmy宣言した場合はサブルーチンにその変数が引き継がれることは知っています。 リファレンス部分で変わるような記述を見たことはあります。 さしあたって問題を感じでいないのです、ふと疑問に思ったのですが、どうもそれに書かれたソースが少ないので御存知の方がいればぜひ御教授願いたいです。 <例> my $hoge; sub hoge1 { $hoge = 1; } sub hoge2 { $hoge = 5; } と sub hoge1 { my $hoge = 1; } sub hoge2 { my $hoge = 5; }

    • ベストアンサー
    • Perl
  • 変数の宣言と使用について

    こんばんは。 数日前から、Javaのプログラミングの学習をしている者です。 とある書籍を読んで、インターネットで調べながら学習しております。 (オブジェクト指向は学習しておらず、三大制御構造まで学習済です。) まだまだ無知な身分であり恐縮ですが、もしよろしければご教授下さい。 ある程度検索しましたが、既に同一の解決済み質問がありましたらご容赦下さい。 当方は、Javaの前にCOBOLとC言語を学習しました。 それらの言語では、変数宣言は処理の最初にまとめて記述していました。 (COBOLはデータ部、C言語は関数内の最初) Javaのソースコードを参考にすると、処理(メソッドブロックなどのブロック内) の最初にまとめて記述しているのではなく 「一文で使用直前に宣言して、同時に初期化代入している」のをよく見掛けます。 Javaでは使用直前に宣言して使用するのがルールであり、 宣言をブロック内の最初にまとめて行っておくのは御法度でしょうか? (個人的にはC言語と同じように記述したいですが、Javaでは逆に 読みにくくなってしまうため、よろしくないという解釈で正しいですか?) 変な質問で大変申し訳ありませんが、ご回答頂けますと嬉しいです。 以上、よろしくお願い致します。

    • ベストアンサー
    • Java
  • 隔絶されているサブルーチン間の通信の方法

    以下のようなFortranのサブルーチンとモジュールがあります。これを見ると、サブルーチンA,Bはモジュールa,bが別なのでデータ的に隔絶されていることになります。もし、このような場合、サブルーチンA,Bの間で何らかの変数を共有するようなことをしたい場合、どのような方法があるでしょうか。サブルーチンの引数を使うのは混乱の原因になりそうなので、できればmoduleの方で処理できないかと思うのですが。 混乱しそうなところなので、やり方をいろいろ比較して見てみたいと思います。Cではグローバル変数のように全体で共有する変数を用意するのかなと思いますが。 module a end module module b end module subroutine A use a end subroutin B use b end Fortranについてはここでは特設会議室はありませんが、どこかいいところがあるでしょうか。Cの専門家はいろんなことに通じていると思うのでここにお尋ねしました。よろしくお願いします。

  • 変数について

    お世話になります。 VBAにてプログラムを作成しています。 本コードで得た変数をCALLのサブルーチン先 でもその変数を生かしたいのですが、empty空 になってしまいます。 変数宣言はPublicにしているのですが。 そう言うものなのでしょうか。 お教え頂きたく宜しくお願い申し上げます。

  • 下記の問題の解き方を教えて下さい。

    主プログラム Main と副プログラム SubX からなる図のプログラムを実行した  後の,変数 A,B の値の組合せとして,正しいものはどれか。ここで,プログラ  ム中の [ ] の部分は,コードの代わりにその内容を記述したものである。  ┌―――――――――┐┌―――――――――――――――――――――――┐  │Main       ││SubX(参照引渡しの仮引数 C ,値渡しの仮引数 D) │  │         ││                       │  │[変数 A の宣言]  ││[変数 E の宣言]                │  │[変数 B の宣言」 ││ E = C                   │  │ A = 1     ││ C = D                   │  │ B = 2     ││ D = E                   │  │Call SubX ( A,B )││                       │  │         ││End Sub                    │  │End        ││                       │  └―――――――――┘└―――――――――――――――――――――――┘    ┌――┬――┐    │ A │ B │  ┌―┼――┼――┤  │ア│ 1 │ 1 │  ├―┼――┼――┤  │イ│ 1 │ 2 │  ├―┼――┼――┤  │ウ│ 2 │ 1 │  ├―┼――┼――┤  │エ│ 2 │ 2 │  └―┴――┴――┘

  • Fortranのサブルーチン引数について

    他人が作ったFortran(恐らくFortran77)のプログラムで計算をしようとしています。 コンパイルはできるのですが,実行するとエラーが出てしまい困っています。 エラーメッセージは 「forrtl:severe(157):Program Exception - access violation」 となっていて,実行時エラー番号で調べると 「プログラムが適切な参照権を持っていない仮想アドレスに書き込み,または読み取り を行おうとした」と出ていました。 Fortran初心者の自分にはイマイチ意味が判らないのですが,エラーが出た後に サブルーチンのある決まった場所に黄色い矢印が示されます。 そこで今,その部分のサブルーチンを確認しているところです。 前置きが長くなってしまいましたが サブルーチンの中を確認している途中で疑問に思った所が一つあります。 問題のサブルーチンは --------------------------------------- call dbesl(EN,0,BX0,BY0,BI0,BK0)     subroutine dbesl(X,NOR,BX,BY,BI,BK) FN = NOR  ・  ・  ・ 11 NOR = FN               <---この行に黄色い矢印が出る return end --------------------------------------- となっているのですが,サブルーチンを呼び出すcall文の所で 2つ目の引数が『0』となっているのは正しい使い方なのでしょうか? どうもサブルーチン内の計算をしてメインプログラムに引数を返す所が おかしいような気がしています。 因みにメインプログラムに戻る際の"FN"の値は『0』となっていました。 コンパイラはCompaq Visual Fortranを使用しています。 足りない情報は出来るだけ追記していきますので,ご教示宜しくお願いします。

  • 文字列配列をサブルーチンにアドレス渡ししてscanf入力

    main関数内で char strarray[3][21] という文字列配列を宣言し、 サブルーチンvoid input(・・・)内でscanfを使って strarray[0]~strarray[2]の各行に入力を行うとします。 ここでポインタを引数としてstrarrayをmainとinputで共有する場合、 strarrayに関して以下の項目はどう記述すればよいのでしょうか? 1)inputを宣言する際の仮引数の書式 2)main内でinputを呼び出す際の引数の書式 3)input内でscanfする際の引数の書式 いろいろ組み合わせを試してはみたのですが、 どうにもSegmentationFaultを回避できません。 いい加減混乱してきたので、そろそろすっきりと整理したいと思っています。 よろしくお願いします。 …まあ「構造体使えばいいじゃないか」と言われてしまえばそれまでなのですが…

専門家に質問してみよう