2016-05-08 7 views
-2

16 0と16 1の32ビットのパーミュテーションのすべてをテキストファイルのvalues.txtに1行ずつ生成しました。 EG-openmpを使ってC++コードを並列化するのに助けが必要

00000000000000001111111111111111 
00000000000000010111111111111111 
00000000000000011011111111111111 
00000000000000011101111111111111 

など....

は、私たちは、テキストファイルの行のそれぞれがブール関数であることを考えてみましょう。 ドメイン内のこの機能の可逆性をチェックする必要があります。

私はこのために、テキストファイルから最初の行を取り出し、次元32x1、行列a [] []の列行列に格納しました。

ネストされたforループの内部私は、基本的に3x3マトリックスの形式でドメイン値を生成しています。そのためには、関数の可逆性をチェックする必要があります。 次元3x3の行列g [] []を作成しました。この行列は、すべての番号のバイナリ表現を格納します。 1から2^9まで。 0行列G用EG- は行列G 2行列Gため

0 0 0 
0 0 0 
0 0 1 

をBE-なり、1ため

0 0 0 
0 0 0 
0 0 0 

like-見える点で最大に

0 0 0 
0 0 0 
0 1 0 

とそうなるであろう2^9。

0〜2^9の上に生成された各行列に対して、私は、自分の関数に基づいて次元3x3の新しい行列u [] []を計算しています。 これは、マトリックスの各要素に隣接する5つの値を読み取ることによって行われます。

EG-は、G行列は

0 0 0 
0 1 1 
1 0 0 

Iピックアップ最初の要素であると考えるため、すなわち、G [0] [0]、それは、5つの隣接する値を使用するための新たな値(TOP値を計算し、 g [0] [0]、g [0] [0]、g [0] [1]、g [1] [g] 0]。これらの5つの番号。組み合わせて2進数を表す。私は10進数の等価を計算し、10進値は行番号に対応します。行列a [] []を使ってu [0] [0]の値を更新する必要があります。 gのすべての要素について上記の処理を繰り返し、最終的に3x3のu行列を得ます。

この完全なプロセスは、1つのマトリックスに対するものであり、それは0に対応する行列です。 0から2^9までのすべてのg [] []行列に対して、これは2^9行列を作成します。

2つの行列g [] []に対して行列u [] []が同じになる場合は、関数を中断してテキストファイルの2行目を読み込み、再度上記の処理を開始します。私は重複行列をもたらす関数には興味がない。 2^9行列のすべてが異なる場合、対応する関数の値(テキストファイルからの行)を別のテキストファイルに書き込みます。

したがって、総計計算のために合計60個のクロア* 2^9行列を作成する必要があります。

テキストファイルの特定の関数の場合、2^9行列は個別に計算されます。何とかそれらを並列化できたら、私は計算時間を大幅に短縮します...

#include <algorithm> 
#include <fstream> 
#include <iostream> 
#include <string> 
#include <math.h> 
using namespace std; 
#include <boost/multiprecision/cpp_int.hpp> 
using namespace boost::multiprecision; 
#include <boost/lexical_cast.hpp> 
#include <cctype> 
#include <boost/assign/list_of.hpp> 
#include <set> 
#include <stdint.h> 
#include <omp.h> 
#define convertToString(x) #x 
using namespace boost::assign; 

int main() 
{ 
    ifstream infile; 
    infile.open("values.txt"); 
    ofstream outfile; 
    outfile.open("haha.txt"); 
    short a[32][1]; 
    while(!infile.eof()) 
    { 
     string STRING; 
     getline(infile,STRING); 
     set<string> SET; 
     int count=0; 


     for(int i=0;i<32;i++) 
     { 
       a[i][0]=STRING.at(i)-'0'; 
     } 


     int g[9]; 
     int u[9]; 
     char buffer[10]; 
     buffer[9] = 0; 
     uint16_t f = 0; 

     int max = (int)pow(2,3); 


     for(int r=0;r<max && count!=1;r++) 
     { 
      for(int s=0;s<max && count!=1;s++) 
      { 
       for(int t=0;t<max && count!=1;t++) 
       { 
       for(int i = 0; i < 9; ++i) 
       { 
        g[i] = (f & (1 << (8 - i))) != 0; 
       } 
       ++f; 

       u[0]=a[(g[6]*2*2*2*2)+(g[2]*2*2*2)+(g[0]*2*2)+(g[1]*2)+(g[3]*1)][0]; 
       u[1]=a[(g[7]*2*2*2*2)+(g[0]*2*2*2)+(g[1]*2*2)+(g[2]*2)+(g[4]*1)][0]; 
       u[2]=a[(g[8]*2*2*2*2)+(g[1]*2*2*2)+(g[2]*2*2)+(g[0]*2)+(g[5]*1)][0]; 
       u[3]=a[(g[0]*2*2*2*2)+(g[5]*2*2*2)+(g[3]*2*2)+(g[4]*2)+(g[6]*1)][0]; 
       u[4]=a[(g[1]*2*2*2*2)+(g[3]*2*2*2)+(g[4]*2*2)+(g[5]*2)+(g[7]*1)][0]; 
       u[5]=a[(g[2]*2*2*2*2)+(g[4]*2*2*2)+(g[5]*2*2)+(g[3]*2)+(g[8]*1)][0]; 
       u[6]=a[(g[3]*2*2*2*2)+(g[8]*2*2*2)+(g[6]*2*2)+(g[7]*2)+(g[0]*1)][0]; 
       u[7]=a[(g[4]*2*2*2*2)+(g[6]*2*2*2)+(g[7]*2*2)+(g[8]*2)+(g[1]*1)][0]; 
       u[8]=a[(g[5]*2*2*2*2)+(g[7]*2*2*2)+(g[8]*2*2)+(g[6]*2)+(g[2]*1)][0]; 


       for(int i = 0; i < 9; ++i) 
       { 
        buffer[i] = '0' + u[i]; 
       } 
       if(!SET.insert(::std::string(buffer)).second) 
       { 
        count = 1; 
       } 
      } 
      } 
     } 

     if(count==0) 
     { 
      outfile<<STRING<<"\n"; 
      cout<<STRING<<"\n"; 
     } 


    } 
     infile.close(); 
     outfile.close(); 
     return 0; 
    } 
+2

正しい字下げは、コードを取得するのに役立ちます... – Aconcagua

答えて

1

二次元のみ1.単純に([0])どこでもあなたがアクセスしている[32]を定義し、2番目のインデックス演算子を省略する場合、二dimenstionalアレイを使用するための必要はありませんが、配列(おそらくは可読性が向上するだけですが、コンパイラはこれを最適化することを期待していますが、安全な側にあります)。

あなたの変換機能は非効率的です。すべての時間を文字列に先行させると、毎回新しい文字列オブジェクトが作成されます。これは、このようなバッファに一度行います。

char buffer[10]; 
buffer[9] = 0; 
for(int i = 0; i < 9; ++i) 
{ 
    buffer[i] = '0' + ((dec & (1 << (8 - i))) != 0); 
} 
return ::std::string(buffer); 

のみすべての16の9桁の数字を出力していないため、何らかの理由はありますか?

ループ内であなたのuアレイの同じ...高い

ワンレベル:

string binary=in.convert(f++); 

for(int i=0;i<9;i++) 
    g[i]=binary.at(i)-'0'; 

あなたはまず、あなたが数字に戻ってそれを変換し、その後、文字列を変換しますか?変換関数に配列を渡して値を直接代入しないでください(0と1ではなく0と1)。

変換機能は単一の場所でのみ使用しています。おそらくインラインにしたいと思うかもしれません。少なくとも、それはどのクラスメンバーにも依存しないため、静的にしてください(他のメンバー関数が残っていない場合は、むしろクラスの代わりに名前空間を持ちます)。


編集:私は単に(プラグマを左)全体のものインライン化の可否:

int g[9]; 
int u[9]; 
char buffer[10]; 
buffer[9] = 0; 
uint16_t f = 0; 

int max = (int)pow(2,3); 
for(int r=0;r<max;r++ 
{ 
    for(int s=0;s<max;s++) 
    { 
     for(int t=0;t<max;t++) 
     { 
      for(int i = 0; i < 9; ++i) 
      { 
       g[i] = (f & (1 << (8 - i))) != 0; 
      } 
      ++f; 
      /* calculate the u array here */ 
      for(int i = 0; i < 9; ++i) 
      { 
       buffer[i] = '0' + (u[i] != 0); 
      } 
      if(!SET.insert(::std::string(buffer)).second) 
      { 
       count = 1; 
      } 
     } 
    } 
} 

事前計算パワーではなく、コンパイラはそれを離れて最適化されていたかどうかわからを...

uおよびg配列のサイズがCPUレジスタサイズと一致する整数型を使用すると、パフォーマンスがさらに向上する場合があります。

あなたの配列aが得られる値はチェックしていません。おそらく、いずれかが可能性があります。ではなく、内、

#pragma omp parallel 
{ 
    for(int r=0;r<(int)pow(2,3);r++) 
    { 
     for(int s=0;s<(int)pow(2,3);s++) 
     { 
      #pragma omp parallel for shared(SET,count,f) 
      for(int t=0;t<(int)pow(2,3);t++) 
      { 
       /* ... */ 
        count = 1; 
        goto EndOfLoop; 
       /* ... */ 
      } 
     } 
    } 
    :EndOfLoop; 
} 

"It is illegal to branch (goto) into or out of a parallel region"

buffer[i] = '0' + u[i]; 

が早く、あなたのループを残す:あなたはこれらの値は常に0または1のみであることを保証した場合、あなたも最小限より多くのコードを短縮することができ私はこれを読んで...バリアントは、すべての3つのループのための

for(int r=0; count == 0 && r<(int)pow(2,3);r++) 

が、もしこれらの追加を持っているだろうコストパフォーマンス...

+0

大きな提案!実際には、私はC++の非常に優れた知識を持っていませんし、HPCで実装しなければならないプロジェクトのためにもそのことを知っていません。もう1つのことは、実際に私の頭を食べているので、openMP行でいくつかの編集を提案することができます、私は必要な出力を得ていません。 :( –

+0

しかしそれは別の質問です - それでは、正確には*必要な出力は何ですか?(遅く返事をして申し訳ありません、私の子供たちと出会った...)。 – Aconcagua

+0

私の質問に説明が追加されました。あなたが出力についての洞察を与えてくれることを願っています。私は良いプログラマではない+ +、私はバッファを使用してあなたの提案を考えたが、私は9ビットのバイナリ表現を必要とするため、同じ出力を得ていなかった、それはちょうど2ビットを返していた。 dec2bin機能を実装していただければ幸いです。 –

関連する問題