Оптимизация Медленный Доступ К Трехмерному Массиву

Тема в разделе "C и С++ FAQ", создана пользователем muaddib1981, 22 мар 2013.

  1. muaddib1981

    muaddib1981 Member

    Регистрация:
    10 янв 2008
    Сообщения:
    8
    Симпатии:
    0
    Требуется перевести буфер из одного формата в другой по определенной формуле с плавающей точкой, а именно из формата yuyv в формат rgb24 (если это что-то кому то скажет).
    Хотел сократить расчеты записав все значения в массив и просто беря оттуда нужные значения.
    Но оказывается что каждый раз считать получается быстрее, вопрос почему?
    Компилятор gcc.
    Привожу тестовый код программы, непосредственный расчет ведется со скоростью 18 циклов/сек, если брать рассчитанные значения из массива - 6 циклов/сек.
    Исходный буфер pbuffer заполняю случайными значения от 0 до 255. Если буфер заполнять константами, то скорость большая, но думаю это из-за оптимизации.

    Код (C++):
    #include <iostream>
    #include <time.h>
    #include <cstdlib>

    using namespace std;

    #define rgb_ptr unsigned char*

    static const int BPP_YUY2 = 2;
    static const int BPP_YUY2_PIXEL = 4;
    static const int BPP_RGB24 = 3;

    unsigned char tableR[256][256][256];
    unsigned char tableG[256][256][256];
    unsigned char tableB[256][256][256];

    inline char clip(int x){
    if (x>255)
    return 255;
    if (x<0)
    return 0;
    return x;
    }

    void yuv2rgb(unsigned char y, unsigned char u, unsigned char v, unsigned char *r, unsigned char *g, unsigned char *b)
    {
    float C = y - 16;
    float D = u - 128;
    float E = v - 128;
    *r = clip(C + ( 1.402 * E ));
    *g = clip(C - ( 0.344136 * D + 0.714136 * E ));
    *b = clip(C + ( 1.772 * D ));
    }

    void fillTables(void)
    {
    int i,j,k;

    for (i=0;i<256;i++)
    {
    for (j=0;j<256;j++)
    for (k=0;k<256;k++)
    yuv2rgb(i,j,k,&tableR[i][j][k],&tableG[i][j][k],&tableB[i][j][k]);
    }

    }

    void getTables(unsigned char y, unsigned char u, unsigned char v, unsigned char *r, unsigned char *g, unsigned char *b)
    {
    *r = tableR[y][u][v];
    *g = tableG[y][u][v];
    *b = tableB[y][u][v];
    }

    void yuyv_to_rgb(rgb_ptr buffer_yuyv, rgb_ptr buffer_rgb, int width, int height)
    {
    rgb_ptr pixel_16;  // for YUYV
    rgb_ptr pixel_24;// for RGB
    int y0, u0, v0, y1;
    unsigned char r, g, b;
    unsigned char r1,g1,b1;
    if ( buffer_yuyv == NULL || buffer_rgb == NULL)
    return;

    pixel_16 = buffer_yuyv;//width * height * 2
    pixel_24 = buffer_rgb;//width * height * 3

    int i = 0, j = 0;
    // while ((i + 2) < height * width * 2)
    for (i=0;i < (height * width * 2 -2);i=i+BPP_YUY2_PIXEL)
    {
    y0 = pixel_16[i];
    u0 = pixel_16[i+1];
    y1 = pixel_16[i+2];
    v0 = pixel_16[i+3];

    //yuv2rgb(y0, u0, v0, &r, &g, &b);
    getTables(y0, u0, v0, &r, &g, &b); // 1st pixel

    pixel_24[j] = r;
    pixel_24[j + 1] = g;
    pixel_24[j + 2] = b;

    //yuv2rgb(y1, u0, v0, &r1, &g1, &b1);
    getTables(y1, u0, v0, &r1, &g1, &b1);// 2nd pixel

    pixel_24[j+BPP_RGB24] = r1;
    pixel_24[j + 1 + BPP_RGB24] = g1;
    pixel_24[j + 2 + BPP_RGB24] = b1;

    j+=BPP_RGB24;
    j+=BPP_RGB24;
    //i += BPP_YUY2_PIXEL;
    }

    }

    int main()
    {
    timespec t1;
    timespec t2;
    double t;
    const int ncycles=100;
    unsigned char *pdata = new unsigned char[1024*768*2]; //yuv
    unsigned char *data = new unsigned char[1024*768*3]; //rgb24

    int i;
    srand(time(NULL));

    fillTables();

    for (i=0;i<1024*768*2;i++)
    pdata[i] = rand() % 255;

    //for (i=0;i<1024*768*2;i++)
    //  pdata[i] = i%255;

    clock_gettime(1,&t1);

    for (i=0;i<ncycles;i++)
    {
    yuyv_to_rgb(pdata,data,1024,768);
    cout<<"#"<<i<<" ";
    cout.flush();
    }

    clock_gettime(1,&t2);

    t= (t2.tv_sec-t1.tv_sec)+(t2.tv_nsec-t1.tv_nsec)/1000000000.0; //складываем секунды и наносекунды
    cout<<"\nTime: "<<t<< "secs\n";
    cout<<"Cycles per sec: "<<ncycles/t<<"\n";

    delete pdata;
    delete data;
    return 0;
    }
     
  2. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Слишком большие таблицы (три по 16777216 байт), кэш страдает.
     
  3. DarkKnight

    DarkKnight Well-Known Member
    C\C++ Team

    Регистрация:
    1 авг 2010
    Сообщения:
    653
    Симпатии:
    0
    А насколько именно "проростает" производительность? и всегда одинаковый ли показатель?
     
Загрузка...

Поделиться этой страницей