高性能创建棋盘图案的方法

时间:2013-08-07 11:52:33

标签: c++ optimization

所以我想要一个用棋盘图案覆盖的图像。 这是我到目前为止所提出的:

for ( uint_8 nRow = 0; nRow < image.width(); ++nRow)
        for (uint_8 nCol = 0; nCol < image.height(); ++nCol)
                  if(((nRow/20 + nCol/20) % 2) == 0)
                        memset(&image.data[nCol + nRow], 0, 1);

遗憾的是,生成白色图像。我不认为这是非常高效的,因为memset是为图像中的每个像素而不是多个像素调用的。 为什么这段代码不会产生chckerboard模式?你会如何改进它?

2 个答案:

答案 0 :(得分:2)

为了获得更好的性能,请勿将图像视为二维实体。相反,将其视为连续数据的一维数组,其中图像的所有行依次排列。

使用这种方法,您可以使用单个循环一次性编写模式,其中在每次迭代中memset()多个相邻像素并将索引增加两倍于您设置的像素数量:

int data_size = image.width() * image.height();
for (auto it = image.data; it < image.data + data_size; it += 20) {
    memset(it, 0, 20);
    if (((it - data) + 40) % (20 * 400) == 0) {
        it += 40;
    } else if (((it - data) + 20) % (20 * 400) != 0) {
        it += 20;
    }
}

(如果您没有使用C ++ 11,请将auto替换为image.data的类型;我怀疑它是unsigned char*。)

这对CPU缓存预取非常友好。它对编译器也很友好,它可以进行矢量化和/或执行循环展开。

答案 1 :(得分:0)

如果您的图片尺寸是方格尺寸的倍数: (我用C编码,但转换到C ++相当容易)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define uint unsigned int
#define WIDTH  40
#define HEIGHT 40
#define BLOCK_SIZE 5

void create_checker_row(uint* row, uint size_block, uint nb_col, uint offset )
{
    uint ic;
    for (ic = size_block*offset ; ic < nb_col; ic+= 2*size_block )
    {
        memset( (row + ic) , 0, size_block*sizeof(uint) );
    }
}

int main()
{
    uint ir,ic;

    // image creation
    uint* pixels = (uint*) malloc(WIDTH*HEIGHT*sizeof(uint));
    for (ir = 0; ir < WIDTH; ir++)
    {
        for ( ic = 0; ic < HEIGHT; ic++)
        {
            // arbitrary numbers
            pixels[ir*WIDTH + ic] = (ir*WIDTH + ic) % 57 ;
            printf("%d,", pixels[ir*WIDTH + ic] );
        }
        printf("\n");
    } 

    for (ir = 0; ir < WIDTH; ir++)
    {
        create_checker_row( pixels + ir*WIDTH   , // pointer at the beggining of n-th row
                            BLOCK_SIZE          , // horizontal length for square
                            WIDTH               , // image width
                            (ir/BLOCK_SIZE) % 2   // offset to create the checker pattern
                            );
    }

    // validation
    printf("\n");
    printf("Validation \n");
    printf("\n");
    for (ir = 0; ir < WIDTH; ir++)
    {
        for ( ic = 0; ic < HEIGHT; ic++)
        {
            printf("%d,", pixels[ir*WIDTH + ic] );
        }
        printf("\n");
    }

    return 0;
}

对我来说似乎很格格:http://ideone.com/gp9so6