2013-04-11 31 views
5

Tôi có một thuật toán đơn giản chuyển đổi kênh hình ảnh bộ đệm (BGGR, RGGB, GBRG, GRBG) thành rgb (demosaicing nhưng không có hàng xóm). Trong triển khai của tôi, tôi đã thiết lập sẵn các vectơ bù đắp giúp tôi dịch chỉ mục kênh bay đến các chỉ số kênh rgb tương ứng của nó. Chỉ có vấn đề là tôi đang nhận được hiệu suất khủng khiếp trong chế độ gỡ lỗi với MSVC11. Theo bản phát hành, cho đầu vào có kích thước 3264X2540, chức năng sẽ hoàn thành trong ~ 60ms. Đối với cùng một đầu vào trong gỡ lỗi, hàm hoàn thành trong ~ 20,000ms. Đó là sự khác biệt lớn hơn X300 và vì một số nhà phát triển đang chạy ứng dụng của tôi khi gỡ lỗi, điều đó không thể chấp nhận được.Sự khác biệt về hiệu năng mạnh mẽ: gỡ lỗi và phát hành

Mã của tôi:

void ConvertBayerToRgbImageDemosaic(int* BayerChannel, int* RgbChannel, int Width, int 

Height, ColorSpace ColorSpace) 
{ 
    int rgbOffsets[4]; //translates color location in Bayer block to it's location in RGB block. So R->0, G->1, B->2 
    std::vector<int> bayerToRgbOffsets[4]; //the offsets from every color in the Bayer block to (bayer) indices it will be copied to (R,B are copied to all indices, Gr to R and Gb to B). 
    //calculate offsets according to color space 
    switch (ColorSpace) 
    { 
    case ColorSpace::BGGR: 
      /* 
      B G 
      G R 
      */ 
     rgbOffsets[0] = 2; //B->0 
     rgbOffsets[1] = 1; //G->1 
     rgbOffsets[2] = 1; //G->1 
     rgbOffsets[3] = 0; //R->0 
     //B is copied to every pixel in it's block 
     bayerToRgbOffsets[0].push_back(0); 
     bayerToRgbOffsets[0].push_back(1); 
     bayerToRgbOffsets[0].push_back(Width); 
     bayerToRgbOffsets[0].push_back(Width + 1); 
     //Gb is copied to it's neighbouring B 
     bayerToRgbOffsets[1].push_back(-1); 
     bayerToRgbOffsets[1].push_back(0); 
     //GR is copied to it's neighbouring R 
     bayerToRgbOffsets[2].push_back(0); 
     bayerToRgbOffsets[2].push_back(1); 
     //R is copied to every pixel in it's block 
     bayerToRgbOffsets[3].push_back(-Width - 1); 
     bayerToRgbOffsets[3].push_back(-Width); 
     bayerToRgbOffsets[3].push_back(-1); 
     bayerToRgbOffsets[3].push_back(0); 
     break; 
    ... other color spaces 
    } 

    for (auto row = 0; row < Height; row++) 
    { 
     for (auto col = 0, bayerIndex = row * Width; col < Width; col++, bayerIndex++) 
     { 
      auto colorIndex = (row%2)*2 + (col%2); //0...3, For example in BGGR: 0->B, 1->Gb, 2->Gr, 3->R 
      //iteration over bayerToRgbOffsets is O(1) since it is either sized 2 or 4. 
      std::for_each(bayerToRgbOffsets[colorIndex].begin(), bayerToRgbOffsets[colorIndex].end(), 
       [&](int colorOffset) 
       { 
        auto rgbIndex = (bayerIndex + colorOffset) * 3 + rgbOffsets[offset]; 
        RgbChannel[rgbIndex] = BayerChannel[bayerIndex]; 
       }); 
     } 
    } 
} 

Những gì tôi đã cố gắng: tôi đã cố gắng Turing về tối ưu hóa (/ O2) cho debug xây dựng không có khác biệt đáng kể. Tôi đã thử thay thế câu lệnh bên trong for_each bằng vòng lặp đơn giản là for nhưng không có kết quả. Tôi có một thuật toán rất giống với thuật toán chuyển đổi bộ đệm sang rgb "xanh" (không sao chép dữ liệu sang các pixel lân cận trong khối) mà tôi không sử dụng std::vector và có sự khác biệt thời gian chạy dự kiến ​​giữa gỡ lỗi và phát hành (X2- X3). Vì vậy, có thể std::vector là vấn đề? Nếu vậy, làm thế nào để vượt qua nó?

+5

Tôi không hiểu. Có chuyện gì vậy? Nó hoàn toàn bình thường, được mong đợi và chấp nhận được, chế độ DEBUG sẽ chậm hơn đáng kể so với chế độ phát hành. Đó là lý do tại sao bạn có hai chế độ khác nhau. Chế độ gỡ lỗi chứa rất nhiều (thực sự rất nhiều) thông tin (siêu dữ liệu) cho mục đích gỡ lỗi. –

+1

@KirilKirov Gỡ lỗi rất hữu ích, nhưng thường quá chậm để có thể sử dụng được. Đó chính là vấn đề. Vì vậy, bạn muốn kích hoạt nó một cách có chọn lọc, chỉ trên các thành phần quan tâm. Đó là giải pháp. –

+0

@KirilKirov: Tôi mong đợi sự khác biệt về hiệu suất giữa gỡ lỗi và phát hành, nhưng tôi chưa bao giờ gặp phải sự khác biệt về hiệu suất của X300. Thuật toán của tôi là một lần lặp đơn đơn giản trên đầu vào. Tôi đã mong đợi một sự khác biệt hợp lý trong thời gian – eladidan

Trả lời

14

Khi bạn sử dụng std::vector, Điều này sẽ giúp tắt gỡ lỗi trình lặp.

MSDN shows how to do it.

Trong thuật ngữ đơn giản, hãy #define này trước khi bạn bao gồm bất kỳ tiêu đề STL:

#define _HAS_ITERATOR_DEBUGGING 0 

Theo kinh nghiệm của tôi, điều này mang lại một lớn tăng hiệu suất của Debug xây dựng, mặc dù tất nhiên bạn sẽ mất một số chức năng gỡ lỗi.

+0

+1. Tôi tin rằng đây là nguyên nhân chính của sự khác biệt, câu trả lời hay. –

+0

@MatsPetersson Đó là "vẻ đẹp" của C++ và STL nói riêng. Một dòng trong chương trình của bạn có thể ẩn khá nhiều thứ. Đôi khi công cụ đó rất tốn kém. –

+0

Tốt, tôi chắc chắn rằng nó sẽ là nó nhưng nó không giúp đỡ ... bất kỳ ý tưởng khác? – eladidan

0

Trong VS, bạn có thể sử dụng các cài đặt bên dưới để gỡ lỗi, Đã tắt (/ Od). Chọn một trong các tùy chọn khác (Kích thước tối thiểu (/ O1), Tốc độ tối đa (/ O2), Tối ưu hóa đầy đủ (/ Ox) hoặc Tùy chỉnh). Cùng với tối ưu hóa trình lặp mà Roger Rowland đã đề cập ...

+0

Như tôi đã đề cập trong bài đăng của mình, tôi đã thử sử dụng/O2 nhưng không có sự khác biệt đáng kể – eladidan

Các vấn đề liên quan