2015-07-21 17 views
2

在某个库(FFTW:离散傅立叶变换计算)中,我遇到了一个头文件,其中包含以下注释和一些#define。评论谈到了一些编程技巧。 但我无法理解这个编程技巧究竟是什么。 有人能解释一下吗?关于开源软件中使用的某种编程技巧的查询

/* hackery to prevent the compiler from ``optimizing'' induction 
    variables in codelet loops. The problem is that for each K and for 
    each expression of the form P[I + STRIDE * K] in a loop, most 
    compilers will try to lift an induction variable PK := &P[I + STRIDE * K]. 
    For large values of K this behavior overflows the 
    register set, which is likely worse than doing the index computation 
    in the first place. 

    If we guess that there are more than 
    ESTIMATED_AVAILABLE_INDEX_REGISTERS such pointers, we deliberately confuse 
    the compiler by setting STRIDE ^= ZERO, where ZERO is a value guaranteed to 
    be 0, but the compiler does not know this. 

    16 registers ought to be enough for anybody, or so the amd64 and ARM ISA's 
    seem to imply. 
*/ 

#define ESTIMATED_AVAILABLE_INDEX_REGISTERS 16 
#define MAKE_VOLATILE_STRIDE(nptr, x)     \ 
    (nptr <= ESTIMATED_AVAILABLE_INDEX_REGISTERS ?  \ 
     0 :            \ 
     ((x) = (x)^X(an_INT_guaranteed_to_be_zero))) 
#endif /* PRECOMPUTE_ARRAY_INDICES */ 

回答

1

优化:代替在每一个循环迭代发生时间重新计算所述阵列的索引的,一些编译器预期的下一个地址,并把这些在寄存器因为索引表达是可预测的。

问题:某些索引表达式(如I + STRIDE * K)可能会导致以这种方式使用大量寄存器,并且如果此数目超过寄存器总数,某些寄存器值将被推送到堆栈内存,包括其他变量该循环可能正在使用。

诀窍:为了强制编译器不使用此优化,将使用外部整数。添加或异或这个零并将其存储在x中是一个无效操作,它会“跨出”步伐,从而导致索引表达式,从而通过优化分析使其不可预知。即使我们知道它的行为非常像零,它不能再推断这个变量的行为。文件ifftw.h的相关提取物作为此导出:

extern const INT X(an_INT_guaranteed_to_be_zero); 

#ifdef PRECOMPUTE_ARRAY_INDICES 
... 
#define MAKE_VOLATILE_STRIDE(nptr, x) (x) = (x) + X(an_INT_guaranteed_to_be_zero) 

#else 
... 
#define ESTIMATED_AVAILABLE_INDEX_REGISTERS 16 
#define MAKE_VOLATILE_STRIDE(nptr, x)     \ 
    (nptr <= ESTIMATED_AVAILABLE_INDEX_REGISTERS ?  \ 
     0 :            \ 
     ((x) = (x)^X(an_INT_guaranteed_to_be_zero))) 
#endif /* PRECOMPUTE_ARRAY_INDICES */ 

这种优化任一未遂完全避免,或者允许在该索引可以在可用的寄存器的数量放入一个猜测的条件。它允许优化的方式是使用一个常数零。

一些词源:宏MAKE_VOLATILE_STRIDE从volatile关键字派生它的名称,它指示值可能会在不同的访问之间改变,即使它看起来没有被修改。此关键字可防止优化编译器优化掉后续读取或写入,从而错误地重新使用旧值或省略写入。 (Wikipedia

为什么挥发性关键字,而不是XOR'ing外部值,是不够的,我不知道。