2014-04-11 1 views
1

디스크에서 이미지를 읽은 다음 자르기 (선택적으로 크기 조정) 한 다음 저장합니다. 하지만 CPU 사용량이 30 % 밖에 안되는 것처럼 보입니다. 다중 스레드를 사용하여 속도 나 디스크 읽기 속도를 향상시킬 수 있습니까? 병목 현상이 있습니까? 최대 성능을 위해 CPU 및 디스크를 올바르게로드하는 방법은 무엇입니까?여러 스레드에서 이미지 읽기

string path = args[0]; 

    int counter = 0; 
    foreach (string dir in Directory.GetDirectories(path)) 
    { 
     Console.WriteLine("processing: " + dir); 

     //create folder for faces 
     string dir_path = dir + "\\face"; 
     System.IO.Directory.CreateDirectory(dir_path); 

     try 
     { 
      string ini_path = dir + "\\.picasa.ini"; 
      if (File.Exists(ini_path)) 
      { 
       FileIniDataParser parser = new FileIniDataParser(); 
       IniData data = parser.LoadFile(ini_path); 
       foreach (SectionData section in data.Sections) 
       { 
        if (section.SectionName.Contains(".jpg")) 
        { 
         string rects = data[section.SectionName]["faces"]; 

         string[] str_rects = GetRectStrings(rects); 

         for (int i = 0; i < str_rects.Length; ++i) 
         { 
          Bitmap img = (Bitmap)Image.FromFile(dir + "\\" + section.SectionName, true); 

          RectangleF rectF = GetRectangle(str_rects[i]); 

          int im_w = img.Width; 
          int im_h = img.Height; 

          rectF.X = rectF.X * im_w; 
          rectF.Y = rectF.Y * im_h; 
          rectF.Width = rectF.Width * im_w; 
          rectF.Height = rectF.Height * im_h; 

          Bitmap bmpCrop = img.Clone(rectF, img.PixelFormat); 

          string text_path = Directory.GetParent(path).FullName + "\\db.txt"; 
          string crop_path = dir + "\\face\\" + 
           Path.GetFileNameWithoutExtension(dir + "\\" + section.SectionName) + "_" + i.ToString() + "_crop.png"; 

          bool resize = true; 
          if (resize) 
          { 
           Bitmap resized = new Bitmap(bmpCrop, new Size(24, 32));//вынести в параметры 
           resized.Save(crop_path, 
            System.Drawing.Imaging.ImageFormat.Png); 

           Bitmap gr = ConvertGray(resized); 

           AppendToTxtFile(gr, text_path); 
          } 
          else 
          { 
           bmpCrop.Save(crop_path, 
            System.Drawing.Imaging.ImageFormat.Png); 

           Bitmap gr = ConvertGray(bmpCrop); 

           AppendToTxtFile(gr, text_path); 
          } 

          counter++; 
         } 
        } 
       } 
      } 

     } 
     catch 
     { 
      Console.WriteLine("problem in: " + dir); 
     } 

     Console.WriteLine("rects: " + counter.ToString()); 
    } 

    Console.WriteLine("all done"); 
    Console.ReadLine(); 
+2

foreach 문 대신 Parallel.ForEach를 살펴보십시오. 이는 해당 코드 블록의 다중 스레드 병렬 실행을 허용해야합니다. – Grax

+0

@ Grax하지만 .net 3.5로 제한됩니다. – mrgloom

+0

조금 더 많은 작업을하지만 루프 안의 코드 블록을 별도의 메서드로 추출하고 스레드 라이브러리를 사용하여 호출 할 수 있습니다. – Grax

답변

2

당신은 모두에게 아마 디스크의 품질이 무엇인지에 따라 약간의 시간이 소요되고 디스크에서 읽기의 요소를 가지고 있지만, 당신은 여전히 ​​이미지 크기 조정의 일반 및 수행 CPU 바인딩 작업에서 IO 작업에 의해 제한된다 .

.NET 3.5에 바인딩 된 경우 이전 비동기 패턴을 사용하는 FileStreams.BeginRead를 사용하여 이미지를 비동기 적으로로드 한 다음 백그라운드 작업자를 최대화하여 이미지 크기를 최대화 할 것을 제안합니다. CPU 사용량.