• ベストアンサー

高次元整数ベクトルの高速計算

VC++2010でwindowsアプリケーション(CLI)を作成しています。 その中で1000次元の整数ベクトルのパワーを求めるために概略次のような計算をしています。 int v[1000]; //v[0]~v[999]に整数値を代入後 long long int power = 0; for(int i = 0; i < 1000; i++){ power += v[i] * v[i]; } この計算を数万回繰り返す必要があるため、是非高速化を図りたいのですが、CPUのベクトル計算機能等を利用して高速化することができるでしょうか?

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

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

こちらで使っている市販コンパイラではベクトル化してもベネフィットはないとメッセージが出てきます。 unrollの最適化はしています。加算していますのでベクトル化は確かにちょっと効果はなさそうに見えます。 関数にして(inlineにはしなくて)遅めのCPUでやってみましたが、1000万回で7秒程度です。 これで遅いのなら、他にも手は有りますが。

softwarelearner
質問者

お礼

有難うございました。 そんなに高速で計算できるのかと思い、よくよく確認をしたところ、計算そのものではなくベクトルへの代入(正確には、代入する値の取得)に時間が掛かっていることが分かりました。お騒がせいたしました。

関連するQ&A

  • 2次元のvectorにオブジェクトのポインタを格納

    VC++6.0です。 まず、ポインタでなく、int型の格納なら分かったんです。 ・・・ #include <vector> using namespace std; main(){ vector <vector<int > > a(10); ←←← for(int i=0;i<10;i++){ a[i].resize(10); } ・・・ for(int j=0;j<10;j++){ for(int i=0;i<10;i++){ a[i][j]=i+j; } } ・・・ } という感じで利用できることが。 しかし、やりたいのは、整数型でなく、 オブジェクトのポインタを格納したいんですが、 矢印部分を例えば、vector <vector<class *> > a(10); などどしてもエラーになってしまいます。 どのように実装したらよいのでしょうか?

  • MySQLでの128次元ベクトルの距離計算高速化

    MySQLで128次元ベクトルの距離計算をしたいと考えています。 ※ 距離と書いていますが、見つけたいのは最も近くにあるデータなので厳密な距離である必要はありません。 ただし、登録されているデータ量やクエリの工夫のなさにより速度が出ない(タイムアウトするレベル)状態です。 そこで、高速化する方法についてご享受ください。 【環境】 OS:CentOS mysql:mysql Ver 14.14 Distrib 5.1.58, for redhat-linux-gnu (x86_64) using readline 5.1 DBに登録されているデータ件数:150万件 総データサイズ:1.6GByte(1レコードあたり1k程度と思われます) カラム数:130      id1,id2,pt1,pt2,…,pt128      int(11),int(11),float,float…,float      近似値計算はfloat部分で行います クエリ: select id1, MIN(POWER(pt1-dat1,2) + POWER(pt2-dat2,2) + … POWER(pt128-dat128,2) ) as 'nearest' from testDB group by id1 order by nearest limit 1 ※dat1は実数です 実行時はCPU使用率が100%であるため、計算量がボトルネックになっているのかなと思っています。 これをなんとか高速化する方法はないでしょうか。 SQLのチューニングや設定の見直し、はたまた次元数を減らす方法等なんでも構いません。 不明、不足な点についてはご指摘いただければ追記させて頂きます。 以上です、よろしくお願い致します。

  • n × n の二次元配列の各要素に vector を突っ込みたいと思っ

    n × n の二次元配列の各要素に vector を突っ込みたいと思っています。 ちょうど三次元グラフで n × n の地表に可変な高さの草が生えてるようなのを想像していただければやりたいことが分かっていただけるかと。 で、このようにしてまずは確保しました。 int i, n = 2; vector<int> ***vecMatrix; vecMatrix = new vector<int>**[ n ]; for (i = 0 ; i < n ; i++) vecMatrix[ i ] = new vector<int>*[ n ]; ここまでは問題ないのですが、次に vecMatrix[ i ][ j ] に対して要素を格納しようとして、 vecMatrix[ 0 ][ 0 ]->push_back( 1 ); とすると segmentation fault で落ちます。 ううーん、なぜでしょう。

  • Vectorによる計算

    名前,値,値,値,値,値,値 ・・・ 中略 ・・・ 名前,値,値,値,値,値,値 以上のフォーマットのCSVファイルを読み込み、 行と列の集計結果を出力するというプログラムを作っています。 Vectorクラスを使うというきまりがあります。 行についてはできたのですが、列の計算方法がわかりません。 どのようにするといいのでしょうか? 以下は私の作成したソースです。 ご助言いただけたらと思います。 宜しくお願いいたします。 import java.util.*; import java.io.*; public class Gyosyukei { public static void main(String args[]) { try{ BufferedReader br = new BufferedReader(new FileReader(args[0])); Vector vc = new Vector(); String str; int retsusu = 0; while((str = br.readLine()) != null){ StringTokenizer st = new StringTokenizer(str,","); int gyosum = 0; for(int i =0;st.hasMoreTokens(); i++){ String token = st.nextToken(); vc.addElement(token); if(i > 0){ int num = Integer.parseInt(token); gyosum += num; } } System.out.println(gyosum); } } catch(IOException e){ } catch(ArrayIndexOutOfBoundsException ae){ } } }

  • 2進表示の大きな整数の余りを求めるには

    こんにちは。 表題のように、VC++で大きな整数の余りを求める方法ですが、与えられるのは2進表示だとします。例えば  1101000101101・・・・・・0010 (256 bit) を  1101001101110010 (16bit) で割った余りを求めたいのです。考えられる方法としてはどんなものがあるでしょうか? ちなみにまともにやろうとすると、2^256クラスの変数が必要となり(10^77のオーダー、long long intでも入りきらず)、C言語ではできないような気がします。 ある人に、ビットハンドリングで2進数のまま計算すればできると言われたのですが、そういう方法はあるんですか?あるなら教えてほしいんです。 よろしくお願いいたします。

  • STLのvectorで・・・

    4次元配列を使いたいので以下のようなプログラムを組んでみました。 -------------------------------------------------- #pragma warning( disable : 4786 ) #include <vector> #include <iostream> using namespace std; void EditYMatrix(vector< vector< vector<int> > > *vi, int i); void EditSquareMatrix(vector< vector<int> > *vi, int i); int main(int argc, char* argv[]) { int i, j, c; vector< vector< vector< vector<int> > > > vi; cout << "Xの要素数を入力してください" << endl; cin >> c; vi.resize(c); cout << "Yの要素数を入力してください" << endl; cin >> c; for(i=0 ; i<vi.size() ; i++) EditYMatrix(&vi[i], c); cout << "Zとωの入力" << endl; for(i=0; i<vi.size() ; i++){ for(j=0; j<vi[i].size() ; j++){ cout << i << "," << j << "番目の自由度を入力してください" << endl; cin >> c; EditSquareMatrix(&vi[i][j], c); } } return 0; } void EditYMatrix(vector< vector< vector<int> > > *vi, int i) { vi->resize(i); } void EditSquareMatrix(vector< vector<int> > *vi, int i) { vi->resize(i); for(int j=0; j<i ; j++) vi[j].resize(i); } -------------------------------------------------- Y,Z,ωは可変で、Zとωは同じにするので、 ためしにこのようなプログラムを組んでみました。 ですが、実行途中でエラーが起きてしまいます。 /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); という部分でエラーが起きているのですが 知識不足で、どのような内容なのかわかりません。 どなたか分かる方教えてください。 OS:Win2000 VC++6.0

  • Vectorの中のVectorについて

    現在Vectorを使ってプログラムを作っています。 その過程でVettorの中に違うVectorを追加していき、追加されたVectorのsize()を出したいのですが、どのように記述すればいいのかがいまいちわかりません。 というより、そもそもそういうことは可能なのでしょうか? 概要としては --------------------------------------------------------- String[] s ={"a","b","c","d","e","f","g","h","i","j"}; Vector v = new Vector(); Vector x = new Vector(); for (int i=0; i<=9; i++) { v.add(i, s[i]); } x.add(v); のように追加されたVectorの中のVetorの大きさ、つまりこの例なら結果としてVector vの中の要素の数10を出したいのです。 size()を使うのだとは思うのですが・・・・・・・・・。 どうすればVectorの中のVectorの要素数を返すことが出来るのでしょうか? ご教授していただければ幸いです。

    • ベストアンサー
    • Java
  • C言語の配列をC++のvectorに高速に変換したい

    質問は表題のとおりです。 単純な方法では以下の通りになると思いますが、 (C言語文字列から string への変換のように) 一括変換の仕組みは vector にないのでしょうか? static const int n=5; int a[n]={0,1,2,3,4}; std::vector<int> v(n); std::vector<int>::iterator vit=v.begin(); for(int i=0; i<n; i++){ *vit++ = a[i]; } 上記の例では n=5 ですが、nがとても大きな場合に適用したいと考えています。 ちなみに、gcc 3.4.3 を使っています。

  • 誤差を出さずに整数計算をしたいです

    いつもお世話になっております。 0~18446744073709551615までの整数値を計算して出力するプログラムを作成しております。 しかし、計算に誤差が出てしまい意図した出力結果が得られません。 試してみた方法と出力は以下のとおりです。 ---------------------------------------------------------------------- [方法1] /* 18446744073709551615に0.0~1.0までの乗算 */ #define RANGE_MAX 18446744073709551615ULL #define MAGNIFICATION 1.0 /* 0.0から1.0 */ printf("%0.lf", RANGE_MAX * MAGNIFICATION); [出力1] 0~18446744073709552000 ---------------------------------------------------------------------- [方法2] /* 562949953421311に0.0~1.0までの乗算した結果と 562949953421312に0.0~1.0までの乗算した結果を 32767回加算した結果を加算する */ #define RANGE_MAX 562949953421312ULL #define MAGNIFICATION 1.0 /* 0.0から1.0 */ #define CYCLE 32767 unsigned long long int y = (RANGE_MAX - 1) * MAGNIFICATION; int loop; for(loop = 0; loop < CYCLE; loop++){ y += RANGE_MAX * MAGNIFICATION; } printf("%llu \n", y); [出力2] 0~9223372036854775808 ---------------------------------------------------------------------- 方法1は丸め誤差が原因だと考え方法2を試してみました。 しかし、方法2では情報落ちになってしまうのか、途中から計算されない 模様です。 誤差を出さずに計算によって0~18446744073709551615までの整数を 得るにはどのようにすれば良いのかご教授願います。

  • 1次元配列をワークシートに高速で転記する方法について質問します。

    1次元配列をワークシートに高速で転記する方法について質問します。 エクセル2000です。 1000万までの範囲で素数を抽出したいと思いました。 そこで下記のようなコードを書きました。 最初は配列にいれず一個ずつセルに転記させたところ664,579個の素数抽出に1分37秒かかったので、配列を用意して下記のようにしたところ1分15秒まで短縮されました。 質問1:配列を使った割には劇的に短縮されないのはなぜでしょうか? 質問2:下記のコードでは最初に取り込んだ1次元外配列をシートに貼るために2次元に変換する際、2次元方向(列)は256で固定、1次元方向(行)は計算で求めたのですが、その結果、要素数が合わず、後の方のデータがない部分が0とシートに出てしまいます。 こうならない方法がありますか? 質問3:一次元配列をワークシートに配置するため二次元配列に変換するのに、もっと良い方法があったらご教示ください。 質問4:配列をワークシートに転記する場合   Application.ScreenUpdating = False   Application.Calculation = xlCalculationManual はあってもなくとも速度に変化がありませんでした。このような貼り付け(配列から一度に転記)には不要なのでしょうか? たくさん質問して申し訳ありません。 宜しくお願いいたします。 Sub test()   Dim t As Date   Dim a As Long, b As Long, c As Long, Num As Long, r As Long, i As Long, x As Long, y As Long   Dim buf As Boolean   Dim myPrm() As Long, myRng() As Long      t = Now()   c = 0   For Num = 2 To 10000000     a = Int(Sqr(Num)) '平方根算出     buf = True     For b = 2 To a '除数       If Num Mod b = 0 Then '割切れたら         buf = False '素数じゃない         Exit For       End If     Next b     If buf Then '割切れなかったら       ReDim Preserve myPrm(c) '添字追加       myPrm(c) = Num       c = c + 1 '素数カウント     End If   Next Num      r = Application.WorksheetFunction.RoundUp((UBound(myPrm) + 1) / 256, 0) '必要行数取得   ReDim myRng(1 To r, 1 To 256) '2次元配列のサイズ変更      For i = LBound(myPrm) To UBound(myPrm) '2次元配列に格納     x = IIf((i + 1) Mod 256 = 0, 256, (i + 1) Mod 256)     y = Application.WorksheetFunction.RoundUp((i + 1) / 256, 0)     myRng(y, x) = myPrm(i)   Next i      Application.ScreenUpdating = False   Application.Calculation = xlCalculationManual   Cells(1, 1).Resize(r, 256).Value = myRng() 'セル範囲に転記   Application.Calculation = xlCalculationAutomatic   Application.ScreenUpdating = True      MsgBox c & "個抽出しました。" & vbNewLine & "所要時間:" & Format(Now() - t, "hh:mm:ss") End Sub