2016-12-03 4 views
3

私はC#をかなり新しくしており、私のコードを最適化する助けが必要です。実行速度のdouble forループを最適化する

struct Data 
{ 
    public static int numberOfPixels; 
    public static string[] filePaths; 
    public static string[] fileNames; 
    public static double[] z; 
    public static int numberOfFrames; 
    public static byte[][] imageBuffer; 
    public static int bufferSize = 1000; 
    public static double[] num; 
    public static double[] den; 
} 
public class Methods 
{ 
    public void RetrieveFileList() 
    { 
     Console.WriteLine("Please enter the folder path where all measurement files are stored: "); 
     Data.filePaths = Directory.GetFiles(Console.ReadLine(),"*.bin"); 
     Data.fileNames = new string[Data.filePaths.Length]; 
     Data.numberOfFrames = Data.filePaths.Length; 
     Data.z = new double[Data.filePaths.Length]; 
     int n = 0; 
     foreach(string file in Data.filePaths) 
     { 
      Data.fileNames[n] = Path.GetFileNameWithoutExtension(file); 
      n++; 
     } 
    } 
    public void CreatePositionArray() 
    { 
     Console.WriteLine("Please enter the stepsize used during the scan in nanometers: "); 
     double stepsize = Convert.ToDouble(Console.ReadLine()); 
     int n = 0; 
     foreach(string file in Data.fileNames) 
     { 
      Data.z[n] = Convert.ToInt32(file) * stepsize/1000; 
      n++; 
     } 
    } 
    public void InitializeBufferArray() 
    { 
     Data.imageBuffer = new byte[Data.numberOfFrames][]; 
    } 
    public byte[] ReadBinaryFile(int index) 
    { 
     return File.ReadAllBytes(Data.filePaths[index]); ; 
    } 
    public void FillImageBuffer() 
    { 
     for (int i = 0; i < Data.bufferSize; i++) 
     { 
      Data.imageBuffer[i] = ReadBinaryFile(i); 
     } 
     Data.numberOfPixels = Data.imageBuffer[0].Length; 
     Data.num = new double[Data.numberOfPixels]; 
     Data.den = new double[Data.numberOfPixels]; 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     Method.RetrieveFileList(); 
     Method.CreatePositionArray(); 
     Method.InitializeBufferArray(); 
     Method.FillImageBuffer(); 
     for(int i = 0; i < Data.numberOfFrames; i++) 
     { 
      for (int j = 0; j < Data.numberOfPixels; j++) 
      { 
       double der = Math.Pow(Data.imageBuffer[i+1][j] - Data.imageBuffer[i][j], 2); 
       if (der < 1) der = 0; 
       Data.num[j] = Data.num[j] + Data.z[i] * der; 
       Data.den[j] = Data.den[j] + der; 
      } 
     } 
    } 
} 

私の主な方法で具体的に二つのループ。現在、このループは約1210000ピクセルの約1000フレームを処理します。外部ループの1回の反復には約80msの実行が必要です。 ここにはどのような方法がありますか? 複数のスレッドを作成し、私のバッファを定義済みのジャンクに分割するか、Parallelクラスを使用しますか? 私はどんな助けにも感謝します。

ありがとうございました。

+0

これはまったく機能しますか? 'Data.imageBuffer [i + 1]'は 'IndexOutOfRangeException'のように聞こえます。 –

答えて

1

おそらく、配列インデックスの参照を減らすためにループ順を逆にする必要があります。また、代わりにMath.Powの(DER、2)、より良い使用デル・デル - それはかなり正直に

 Method.RetrieveFileList(); 
    Method.CreatePositionArray(); 
    Method.InitializeBufferArray(); 
    Method.FillImageBuffer(); 
     for (int j = 0; j < Data.numberOfPixels; j++) { 
     double num = 0 
     double den = 0; 
     for(int i = 0; i < Data.numberOfFrames; i++) { 
      double der = Data.imageBuffer[i+1][j] - Data.imageBuffer[i][j]  
      if ((der *= der) < 1) der = 0; 
      num += Data.z[i] * der; 
      den += der; 
     } 
     Data.num[j] = num; 
     Data.den[j] = den; 
    } 

少し速くですが、私はそれがdrammaticallyパフォーマンスを向上させるとは思いません。

+0

私はそれが好きです!また、 'der = 0;'は 'continue;'で置き換えられ、トップループは 'Parallel.For'に簡単に変換できます。 +1 –

+0

ありがとう、イワン。 Parallel.Forは本当の感覚です。また、 "contunue"を嫌う人は、代わりに "if(der * der> = 1){num + = ...; den + =。}を使うことができます:) – cyanide

0

私はしばらくの間、 "あまりにも多くのループ"を行ってきましたが、これと同じ問題がありました。私は9100万回ループし、約4-5分かかりました。これを20-30秒に分解するために私が行ったことはプロファイリングでした。あなたは、Visual Studioのプロファイラを試してみる必要があります。どのコード行がプログラムのパフォーマンスを劇的に低下させるかを実際に知るのに役立ちます。私は誰もGPGPU(GPUの一般的なプログラミング/など)について言及していないことに気づいた。あなたのコードを各フレームで実行したい場合、GPGPUはそれを行うことができます! OpenCL、Cudafy、またはDirectX/OpenGLの計算シェーダを使用することができます。 GPUプログラミングをしたくない場合は、VSプロファイラを使用するのがベストプラクティスです。

関連する問題