• 締切済み

膨大データ処理を高速化したい

仕事上、膨大データ処理を行っており、その処理に一度の処理に何十分も掛かり困ってます。 OSはWindows7でCPUはCore5、メモリ4GBの環境でも何せこれだけの膨大データなので。 その方法としてインメモリというメモリに対象データを格納してHDDを介さず高速データ処理が可能な技術もあるそうですが、どうやらそれは個人向けの技術ではなさそうですね。 ですが膨大データ処理を行ってる以上、高速処理を実現させる必要があり、できれば個人でもインメモリを実現させたいです、またインメモリに代わる高速処理の方法があれば教えて下さい。

みんなの回答

  • wormhole
  • ベストアンサー率28% (1626/5665)
回答No.25

>C99は、コメントで//が使えるので対処してると思います C99に関係なく // をコメントとして扱えるCコンパイラは多数あるのでコメントで // が使えるからといってC99だとは限りません。 >-std=c99はググってみたが検索結果無しでした。 >for(int i=0;i<100000;i++)の様に iをfor文内で宣言するとうちの場合、コンパイルエラーになります。 >-O2 -O3の記号についてググってみたが、それに関する記述は見当たりませんでした。 mingwのCコンパイラはGNU C(gcc)なのでGNU Cのマニュアルを参照すればだいたいはわかると思います。 https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html コンパイルエラーになるのは-std=c99を指定していないからです。 そもそもコンパイルエラー時に出力されるメッセージにそのように書いてありませんでしたか?(プログラムを作ろうとするならエラーメッセージを読まずにエラーとだけ認識するのは止めましょう) 私はmingwは使用していませんのでFreeBSDのgcc 4.9でですが以下のように「use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code」と出力されますが(プラットフォームに依存する部分ではないのでバージョンによる差異はあれmingw環境でも同じようなメッセージが出力されるはず)。 >% cat for.c >#include <stdio.h> > >int >main(int argc, char **argv) >{ > for (int i = 0; i < argc; i++) > printf("%s\n", argv[i]); > return; >} > >% gcc49 -o for for.c >for.c: In function 'main': >for.c:6:3: error: 'for' loop initial declarations are only allowed in C99 or C11 mode > for (int i = 0; i < argc; i++) > ^ >for.c:6:3: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code >% >wormholeさんの提示されたプログラムを実行してみましたが、 私は何のプログラムも提示していませんけど?

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 返答遅れてすいません。 最初で書いた通り、利用してるソフトでの処理を高速化できないものかと願い質問スレッドを立上げさせて戴いております。 数日前になり、実はそのソフトがアップデートをされてる事を知り、ソフトを再インストールしてみると、処理のスピードが二倍くらいの速さになっており、データを一通りの処理に掛かる時間は6秒代の速さになってました。 処理するデーターが170万行以上で容量も223MBもある事を考えれば、このぐらいのスピードがあれば速い方ではないかと感じます。 皆さんの回答に対して失礼な事を言いますが、私の目指してる事は、高速処理のスクリプトの開発でなく、データー処理を高速化してそのソフトを利用した作業ネックの解消であり、そのアップデートしたソフトの処理の速さをみて、今回の問題は一応解決という形になったと思います。 皆さんのお陰てC言語スクリプトで並列処理をする初歩的な事についてアドバイスして戴いた事はプログラミングする上で役立つ情報を得たと思います。

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

No.23への返事をいただいてから大事な事は書こうと思ってますが、 簡単なNo.20の補足欄について >処理速度が速くなったという感じはしませんでした。 当然です。No.21のwormholeの回答をもう一度見てください。そこにちゃんと書いてあります。 それを防ぐためにNo.17にプログラムを書いておいたのですが、それをそのまま実行してみてください。 並列化は時々やりますが、現実には並列化が不可能なものもかなり有ります。また並列化したとしても全然速くならないこともあります。openMPの場合は手で設定しないといけないので、並列化について正確に理解していなとマトモに動きません。バグだらけになる可能性がかなり高いです。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 返答遅れてすいません。 最初で書いた通り、利用してるソフトでの処理を高速化できないものかと願い質問スレッドを立上げさせて戴いております。 数日前になり、実はそのソフトがアップデートをされてる事を知り、ソフトを再インストールしてみると、処理のスピードが二倍くらいの速さになっており、データを一通りの処理に掛かる時間は6秒代の速さになってました。 処理するデーターが170万行以上で容量も223MBもある事を考えれば、このぐらいのスピードがあれば速い方ではないかと感じます。 皆さんの回答に対して失礼な事を言いますが、私の目指してる事は、高速処理のスクリプトの開発でなく、データー処理を高速化してそのソフトを利用した作業ネックの解消であり、そのアップデートしたソフトの処理の速さをみて、今回の問題は一応解決という形になったと思います。 皆さんのお陰てC言語スクリプトで並列処理をする初歩的な事についてアドバイスして戴いた事はプログラミングする上で役立つ情報を得たと思います。

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

枝葉の話になってしまったので、少し戻します。 1) ソフト用の独自言語でコンパイルしていて、数値計算だということは分かったのですが、どのようなタイプの数値計算なのでしょうか? a) 集計タイプ、データの傾向をつかんだり統計的な処理などが考えられますが、これだと数十分はかなり遅すぎるように思います。集計などに特化したソフトウエアがありますので、それを使うことで速くて分かり易いプログラムを作れます。 b) シミュレーションタイプ、時系列に変化を予測していくものなど。計算量を削るのは難しいので力ずくで計算を速くするしかなさそう。ただし、このタイプのソフトは多くは公開されていますので探すと結構あります。 c) 収束タイプ、最適な組み合わせを見つけるものなどがありますが、同じく探せば結構みつかります。 2) ソフト用のC言語に似ている独自言語でコンパイルしていてとありますが、独自言語をいうのは何なのでしょうか? まさかその人が独自で開発した言語ではないとは思いますが。 上のa)でも独自言語で書くソフトが多いのですが、マトモに書けばそれほど遅くはなりません。 数値計算をよくやりますが、99%は上のようなやり方で済みます。残り1%くらいは自分で書かないといけないことも有るのですが、ボトルネックの部分だけCやFortranで書くのでせいぜい20行程度です。 データを読み込んでそれを公開されているプログラムに渡す部分だけ自分で書く場合がほとんどです。一般に言われているスクリプト言語で書けばあっという間に書けますので、こうしたやり方が効率的です。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 返答遅れてすいません。 最初で書いた通り、利用してるソフトでの処理を高速化できないものかと願い質問スレッドを立上げさせて戴いております。 数日前になり、実はそのソフトがアップデートをされてる事を知り、ソフトを再インストールしてみると、処理のスピードが二倍くらいの速さになっており、データを一通りの処理に掛かる時間は6秒代の速さになってました。 処理するデーターが170万行以上で容量も223MBもある事を考えれば、このぐらいのスピードがあれば速い方ではないかと感じます。 皆さんの回答に対して失礼な事を言いますが、私の目指してる事は、高速処理のスクリプトの開発でなく、データー処理を高速化してそのソフトを利用した作業ネックの解消であり、そのアップデートしたソフトの処理の速さをみて、今回の問題は一応解決という形になったと思います。 皆さんのお陰てC言語スクリプトで並列処理をする初歩的な事についてアドバイスして戴いた事はプログラミングする上で役立つ情報を得たと思います。

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

wormholeさんからツッコミがありますがよく考えてみてください。 openMPで並列化を実感するのも良いのですが、まずはC言語なりに書き換えられてはいかがでしょうか? openMPはどちらかと言うと、既存のプログラムを最小限の手直しで並列化しようとするものです。 コンパイルするときに-O2か-O3(こちらは注意が必要なときもある)オプションを付けてやるだけでも、古いものよりも何倍かははやくなることもあり得ます。 それと、C言語のC99対応で書かれることをお勧めします。 constを可能な限り付けておく(実行中に値が変わらないことをコンパイラが知ることができるので最適化しやすい) もう一つはforの変数をやその中だけで使う変数はその場で宣言する。 例えば for(i=0;i<100000;i++)を for(int i=0;i<100000;i++) のようにします。変数の使用範囲が明確になるので同じく最適化しやすくなります。openMPにしたときもprivate宣言が必要なくなりますので、バグの原因が減ります。 ただしgccの場合は-std=c99を付けないとエラーになります。 C99とは関係ありませんが、ポインターの使用は必要最低限にし、なるべく配列を使う。昔であればポインターの使用でバイナリがコンパクトになり結果的に速くなっていましたが、今ではコンパイラの最適化の邪魔をする可能性が多々あります。 これだけ注意するだけで良いと思います。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 C99は、コメントで//が使えるので対処してると思います。 -std=c99はググってみたが検索結果無しでした。 for(int i=0;i<100000;i++)の様に iをfor文内で宣言するとうちの場合、コンパイルエラーになります。 -O2 -O3の記号についてググってみたが、それに関する記述は見当たりませんでした。 wormholeさんの提示されたプログラムを実行してみましたが、gprof gmon.outのコマンドによるプロファイラ起動はどうしても test: No such file or directry と必ず出て成功できません。 またgprof gmon.outの入力前に/.testを入力しますが/.はコマンドとして認識されないので test のみ入力して実行してますがこれでよいのでしょうか? それにしてもopenMPてやや高度な技術ですよね。

  • wormhole
  • ベストアンサー率28% (1626/5665)
回答No.21

>あるソフトを使って膨大データの処理をやってるんですが、あまりにも時間が掛かるのでもっと高速で処理できないかと考え、別ソフトか自作のC言語スクリプトで高速処理を実現させようと模索してます。 「C言語スクリプト」とはふつういいませんけど・・・というのは置いとくとして #14の補足の「プロンプトでの処理だとソフトウェアより遥かに時間が掛かってしまってます。」は「自作プログラムでの処理だと現在使用しているソフトウェアより遥かに時間が掛かってしまってます。」という事であってますか? 自作プログラムを動かす事を「プロンプトでの処理」とか書かれても他者には伝わらないです。 また#15の補足で「並列処理を実行し、次にopenMP(#include <omp.h>)を外し普通の実行もしてみましたが全然速くなった感じはしませんでした。」と書かれていますが試されてる内容的に並列処理したところで早くなりそうにないものなんですが・・・(どんなに並列でprintfしようが実際に出力できるのは1つのみなので順番待ちになってるはず) #14の補足で「分割はまず無理だと思います」と書かれているのに並列処理を試そうとされてるのもよくわかりませんし。 高速化するために無計画に手当たり次第にやったところで無駄が多いだけだと思うんですけど。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 >「プロンプトでの処理だとソフトウェアより遥かに時間が掛かってしまってます。」は >「自作プログラムでの処理だと現在使用しているソフトウェアより遥かに時間が掛かってしまってます。」 そうです。 >#14の補足で「分割はまず無理だと思います」と書かれているのに並列処理を試そうとされてるのもよくわかりませんし。 分割と並列処理を別々のモノと思いその様な言い方になりました。 何故、分割が無理かと言いますと、並列処理に関係なく自分の目指してる処理とは、ある数値データを最初から順番に計算を実行して行かなければ正しい回答が出せないからです。 データを分割して順番飛び飛びの計算では正しい計算結果は得られません。 >試されてる内容的に並列処理したところで早くなりそうにないものなんですが・・・ >(どんなに並列でprintfしようが実際に出力できるのは1つのみなので順番待ちになってるはず) プロンプトで実行してみてもそんな感じにデータを順番に一つずつ出力してる感じです。 >高速化するために無計画に手当たり次第にやったところで無駄が多いだけだと思うんですけど。 そうかもしれませんね、高速処理に奔走した切っ掛けは使ってるソフトがある計算処理に時間を掛かってる事に悩み、そのソフトに関するページを見てみると、マルチコア非対応で処理が遅い書込みを多く見たのが切っ掛けで、マルチコアに対応できるプログラムやソフトを手に出来ればその問題が解決できる期待があると考えたです。 そもその計算対象のデータは170万行強もある膨大データで、170万行強を外部入力で数値を全行の数値に与える計算を外部入力値を替えながら何十周もする処理なので時間が掛かる訳です。 一周の処理には14秒くらい掛かります、つまり14秒*何十周という訳です。 プロンプトでのC言語スクリプトの処理を行ってる目的は、試験的どうやったら高速処理が出来るかその基本になるものだからです。

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

このあたりを参考に http://demura.net/misc/7168.html

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 回答18の方から紹介されたURLから https://www.sourceware.org/pthreads-win32/ lpthreadのデータを探してるが見つからずMinGW関連ページを見回ってる内にlibpthreadGC2.aがlibフォルダにない事が解りもう一度同じURLから探した所、libpthreadGC2.aが見つかり名称を libpthread.aに替えて gcc -fopenmp oc.c -o bvc のコマンド入力したところコンパイルを通す事ができました。 そして並列領域指定のコマンド set OMP_NUM_THREADS=10 を入力して実行してみましたが処理速度が速くなったという感じはしませんでした。 そしてプロファイラコマンドはlibpthreadが通っても以下のとおり (入力コマンド) gcc -pg -o oc3 oc.c (入力コマンド) oc            (実行完了) (入力コマンド) gprof oc gmon.out (結果)No such or directry と返され出来る様になりませんでした。 一応私の実行してるC言語ソースを貼っときます。 #include <stdio.h> #include <omp.h> int main() { int i,s; #pragma omp parallel { #pragma omp for for(i=0;i<500000;i++){ s=i*20+(180-60)*3; printf("(%d) S=%d\n",i,s); } } return 0; } 宜しくお願いします。

  • wormhole
  • ベストアンサー率28% (1626/5665)
回答No.19

>回答を拝見した後、ソフトウェアで時間の掛かる処理だけならプロンプトでの実行でどうにかならないかという方法を思い立ちボーランドC++をインストールして膨大データの処理のスクリプトを作成、コンパイルして試してみましたが、プロンプトでの処理だとソフトウェアより遥かに時間が掛かってしまってます。 「膨大データの処理のスクリプトを作成、コンパイルして試してみましたが」と書かれていましたが何をどう試されたんですか? 「プロンプトでの処理」というのもわかりませんし。

cs4f18df
質問者

補足

あるソフトを使って膨大データの処理をやってるんですが、あまりにも時間が掛かるのでもっと高速で処理できないかと考え、別ソフトか自作のC言語スクリプトで高速処理を実現させようと模索してます。 そしてプロンプトでのスクリプトの実行こそプログラムの基礎であり、ソフトに頼らずスクリプトから自作でやる事がソフトだと用意された処理というアクションの範囲に限定されますが、自作なので範囲に限定はなく自分の思いのままの処理やパフォーマンスができると期待してその処理試してる次第です。

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

要するにlibpthreadが入ってないということです。 https://www.sourceware.org/pthreads-win32/ から入手できるようです。ftpを使うのに手間がかかるようでしたら、mirrorサイトにhttpを使えるところがあります。 Windowsでは「コマンドプロンプト」でしたっけ、プログラムを実行する前に set OMP_NUM_THREADS=4 を実行する必要があります。「コマンドプロンプト」に初期設定のようなもので環境変数設定できるのならしておくといちいち書かなくても便利かもしれません。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 提示されたURLにアクセスしてlibpthreadを探しました。 膨大なディレクトリの中に様々なデータが置かれており、どれを取込めばいいのかチンプンカンプンでしたが色々とMinGWに関するページを見ているうちにこれかなと考え pthreads-w32-2-8-0-release のセットをダウンロードしましたが、展開してみるとおびただしい数のC言語スクリプトが山ほど入っており、それらをどの様にセッティングすればよいのかさっぱり解りません。 また libpthread-2.8.0-3-mingw32-dll-2.tar を別ページからダウンロードしlibpthread-2.dllを MinGW/bin に置いて gcc -fopenmp oc.c を実行しましたが、相変わらず c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lpthread collect2.exe: error: ld returned 1 exit statusgcc -fopenmp oc.c というエラーに跳ね返りました。 MinGWを理解する事てホント難しいですね。 何度もすいませんが、ご教授宜しくお願いします。

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

No.15の補足欄について いくつか足りない所があります。 まず,環境変数OMP_NUM_THREADSをコア数にしておく必要が有ります。当方はUNIX系OSなのでexportでできるのですが、Windowsはやった事がありません。 http://www.nag-j.co.jp/openMP/openMPOpenMpBackgroundInformation.html からすると、set OMP_NUM_THREADS=4のような感じですかね それとコンパイルのときに、 gcc -O2 -fopenmp -o test test.c のように-fopenmpが必要なはずです。こちらでやったプログラムを書き込んでおきます。 #include <stdio.h> #include <omp.h> float sum1() { int i, j; float sum; sum=0.0; #pragma omp parallel for private(i) reduction(+:sum) for(j=0; j<10000; j++) for(i=0;i<100000;i++) sum=sum+(i+j)/20000.0; return sum; } int main() { printf("%f\n", sum1()); return 0; } 遅いCore2 Duoでやって real 0m16.962s とopenMPで real 0m8.529s です。これくらい遅いとCPU使用率が見えます。 gcc -pg -o test test.c ./test gprof test gmon.out で表示されます。上のプログラムの結果です。 % cumulative self self total time seconds seconds calls s/call s/call name 101.08 2.04 2.04 1 2.04 2.04 sum1 以下省略。gccって関数しか出力しないのかな??

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 言われた事を試そうと先ず gcc -fopenmp oc.c をコマンド入力しましたが c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: cannot find -lpthread collect2.exe: error: ld returned 1 exit statusgcc -fopenmp oc.c というエラーが返りできません。 どの様にすればfopenmpが通るか教えて下さい。 また set OMP_NUM_THREADS=4 のコマンドは set OMP_NUM_THREADS=4 oc.exe の様に実行する時にコマンド入力すれば宜しいのでしょうか? 宜しくお願いします。

noname#214300
noname#214300
回答No.16

>別の質問掲示板で私の使ってるソフトを使用してる人がマルチコア非対応なのでCore i7のPCでも速くならなかったと書かれてたのを読みました。 私が4790Kと書いたのは、民生で買えるCPUでシングルスレッド性能が最も良い(とにかくクロックが一番速い)からです。マルチスレッド動作は一切考慮していません。 >ボーランドC++をインストールして膨大データの処理のスクリプトを作成、コンパイルして試してみましたが、プロンプトでの処理だとソフトウェアより遥かに時間が掛かってしまってます。 ご自分でロジックを書けるなら、クラウドアウトソーシングなどでマルチスレッド対応のプログラムでも作って貰った方が早いのでは? どんなデータなのか、どんなロジックなのか補足も無いようでは、いつまで経ってもロクな回答は出てこないと思われます。 アルゴリズム的にどうしても時間が掛かるのならば、お金に物を言わせるか(どこかのスパコンでも時間貸しで借りるのも良いでしょう。AWSにもそういうサービスはありますし)、賢い人に頼むか、寝る前に仕掛けて朝結果が出来てくるのを待つしかありません。

cs4f18df
質問者

補足

回答、情報提供どうもありがとうございます。 個人でスパコンを無料で試せる事は魅力的ですね。 ですがどんなに高性能なCPUやゆとりのあるメモリがあっても先ずは並列処理ができるプログラムが作れる必要があるかなと感じます。 ズブの素人が並列処理ができるプログラムOPENmpをまともに 扱えるまでやや苦労が必要な状況です。

関連するQ&A