-2

我正在做一个旋转二维数组的项目。当我使用宏替换一些代码时,结果令人惊讶,因为一切都完全一样。完成任务所需的时间可能会有很大不同。我一直认为宏只是一个占位符,但这怎么可能发生呢?

struct pixel
{
    unsigned short red;
    unsigned short green;
    unsigned short blue;
} ;

//n is the # of elements in the two dimensional array
void rotate1(int n, pixel *src, pixel *dst)
{
    int row, col, max = n - 1;
    for (row = 0; row < n; row++)
        for (col = 0; col < n; col++)
            *(dst+ (((max - row)*n)+col)) = *(src+ (row*n + col));
}

void rotate11(int n, pixel *src, pixel *dst)
{
#define TARGET  *(dst + (((max - row)*n)+col))
#define SOURCE  *(src + (row*n + col))

    int row, col, max = n - 1;
    for (row = 0; row < n; row++)
        for (col = 0; col < n; col++)
        {
            TARGET = SOURCE;
        }

}

结果是:

Time= 2.25 n= 512  Method= rotate1 
Time= 2.18 n= 512  Method= rotate11 

Time= 8.05 n= 1024  Method= rotate1 
Time= 8.08 n= 1024  Method= rotate11 

Time= 25.18 n= 2048  Method= rotate1 
Time= 25.24 n= 2048  Method= rotate11 

Time= 104.38 n= 4096  Method= rotate1 
Time= 104.21 n= 4096  Method= rotate11

Time= 1272.41 n= 8192  Method= rotate1 
Time= 423.00 n= 8192  Method= rotate11

当 n 较小时,两者具有相似的性能,但随着 n 变得越来越大,所rotate11花费的时间越来越少。

4

4 回答 4

7

就您的编译器而言,这两个示例是相同的。您是否在同一运行中运行这两个示例?可能发生的情况是第一个运行的函数(无论您是否使用宏)正在填充缓存,因此第二个运行得更快。

如果您更改调用函数的顺序,或限制每次执行只运行一个函数怎么办?您应该看到几乎相同的性能。

于 2013-11-07T20:50:12.223 回答
1

这里有一个稳定的增长模式——正如@mah 指出的那样——每次增长n2 倍,运行时间就会增长 4 倍,这是有道理的,因为你的数组是 n^2。

据此,您的最后一次通话 (n=8192) 应该是 ~400 长,正如第二次通话确实显示的那样。我敢打赌,在第一次调用(上下文切换或其他中断)期间只是发生了一些意外事件,导致它停滞不前——你应该运行一些迭代,看看它是否重现

于 2013-11-07T21:22:31.880 回答
1

我怀疑内存缓存的一些影响。为了确保您可以尝试进行 4 次调用,run1、run11、run 1、run11,您的数据具有内存访问模式,这可能会导致第一次加载数据的成本很高......

于 2013-11-07T20:58:33.197 回答
0

在编译器看到代码之前,宏由 C 预处理器扩展。

您可以通过 gcc 中的 -E 选项创建预处理器输出。

例如:

gcc -E foo.c -o foo.i /* 创建预处理器文本文件输出 */

对比

gcc -c foo.c -o foo.o /* 创建目标文件输出 */

如果在您选择的编辑器中打开 foo.i,您将看到宏扩展为源代码。

我真的不明白 MACROS 是如何影响你的表现的。

于 2013-11-07T21:15:29.400 回答