2012-09-18 48 views
1

我正在寫一個圖像處理程序,其目的是爲了改變大圖像,我正在使用的圖像處理程序是8165像素×4915像素。我被告知要執行GPU處理,所以經過一些研究後,我決定與OpenCL一起使用。我開始實施OpenCL C#封裝OpenCLTemplate。使用c#和opencl的內存對象分配失敗

我的代碼需要一個位圖並使用鎖定位來鎖定其內存位置。然後,我將每一位的順序複製到一個數組中,通過openCL內核運行該數組,並將數組中的每一位反轉。然後,我將反轉的位返回到圖像的內存位置。我將這個過程分成十個塊,這樣我可以增加一個進度條。

我的代碼完美適用於較小的圖像,但是當我試圖運行它與我的大圖像時,我試圖執行內核時不斷收到MemObjectAllocationFailure。我不知道爲什麼要這樣做,我希望能找出解決問題的原因或解決方法。

using OpenCLTemplate; 

    public static void Invert(Bitmap image, ToolStripProgressBar progressBar) 
    { 
     string openCLInvert = @" 
     __kernel void Filter(__global uchar * Img0, 
          __global float * ImgF) 

     { 
      // Gets information about work-item 
      int x = get_global_id(0); 
      int y = get_global_id(1); 

      // Gets information about work size 
      int width = get_global_size(0); 
      int height = get_global_size(1); 

      int ind = 4 * (x + width * y); 

      // Inverts image colors 
      ImgF[ind]= 255.0f - (float)Img0[ind]; 
      ImgF[1 + ind]= 255.0f - (float)Img0[1 + ind]; 
      ImgF[2 + ind]= 255.0f - (float)Img0[2 + ind]; 

      // Leave alpha component equal 
      ImgF[ind + 3] = (float)Img0[ind + 3]; 
     }"; 

     //Lock the image in memory and get image lock data 
     var imageData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 

     CLCalc.InitCL(); 

     for (int i = 0; i < 10; i++) 
     { 
      unsafe 
      { 
       int adjustedHeight = (((i + 1) * imageData.Height)/10) - ((i * imageData.Height)/10); 
       int count = 0; 

       byte[] Data = new byte[(4 * imageData.Stride * adjustedHeight)]; 
       var startPointer = (byte*)imageData.Scan0; 

       for (int y = ((i * imageData.Height)/10); y < (((i + 1) * imageData.Height)/10); y++) 
       { 
        for (int x = 0; x < imageData.Width; x++) 
        { 
         byte* Byte = (byte*)(startPointer + (y * imageData.Stride) + (x * 4)); 

         Data[count] = *Byte; 
         Data[count + 1] = *(Byte + 1); 
         Data[count + 2] = *(Byte + 2); 
         Data[count + 3] = *(Byte + 3); 
         count += 4; 
        } 
       } 

       CLCalc.Program.Compile(openCLInvert); 
       CLCalc.Program.Kernel kernel = new CLCalc.Program.Kernel("Filter"); 
       CLCalc.Program.Variable CLData = new CLCalc.Program.Variable(Data); 

       float[] imgProcessed = new float[Data.Length]; 

       CLCalc.Program.Variable CLFiltered = new CLCalc.Program.Variable(imgProcessed); 
       CLCalc.Program.Variable[] args = new CLCalc.Program.Variable[] { CLData, CLFiltered }; 

       kernel.Execute(args, new int[] { imageData.Width, adjustedHeight }); 
       CLCalc.Program.Sync(); 

       CLFiltered.ReadFromDeviceTo(imgProcessed); 

       count = 0; 

       for (int y = ((i * imageData.Height)/10); y < (((i + 1) * imageData.Height)/10); y++) 
       { 
        for (int x = 0; x < imageData.Width; x++) 
        { 
         byte* Byte = (byte*)(startPointer + (y * imageData.Stride) + (x * 4)); 

         *Byte = (byte)imgProcessed[count]; 
         *(Byte + 1) = (byte)imgProcessed[count + 1]; 
         *(Byte + 2) = (byte)imgProcessed[count + 2]; 
         *(Byte + 3) = (byte)imgProcessed[count + 3]; 
         count += 4; 
        } 
       } 
      } 
      progressBar.Owner.Invoke((Action)progressBar.PerformStep); 
     } 

     //Unlock image 
     image.UnlockBits(imageData); 
    } 

回答

0

您可能已達到OpenCL驅動程序/設備的內存分配限制。檢查clGetDeviceInfo返回的值。單個內存對象的大小是有限制的。 OpenCL驅動程序可能允許所有分配的內存對象的總大小超過設備上的內存大小,並且會在需要時將它們複製到主機內存或從主機內存複製它們。

要處理較大的圖像,您可能必須將它們分成較小的部分,並分別處理它們。