【发布时间】:2021-12-01 04:31:00
【问题描述】:
Part 1 - why the code below checks st_inverse in the first place
kiss_fft 代码有这个分支在循环中:
do {
if(st->inverse) {
Fout[m].r = scratch[5].r - scratch[4].i;
Fout[m].i = scratch[5].i + scratch[4].r;
Fout[m3].r = scratch[5].r + scratch[4].i;
Fout[m3].i = scratch[5].i - scratch[4].r;
}else{
Fout[m].r = scratch[5].r + scratch[4].i;
Fout[m].i = scratch[5].i - scratch[4].r;
Fout[m3].r = scratch[5].r - scratch[4].i;
Fout[m3].i = scratch[5].i + scratch[4].r;
}
++Fout;
} while (--k); // Fout[] has k*4 elements.
稍微重新排序:
if(st->inverse) {
Fout[m].r = scratch[5].r - scratch[4].i;
Fout[m].i = scratch[5].i + scratch[4].r;
Fout[m3].r = scratch[5].r + scratch[4].i;
Fout[m3].i = scratch[5].i - scratch[4].r;
}else{
Fout[m3].r = scratch[5].r - scratch[4].i;
Fout[m3].i = scratch[5].i + scratch[4].r
Fout[m].r = scratch[5].r + scratch[4].i;
Fout[m].i = scratch[5].i - scratch[4].r;;
}
这两个代码块的真正区别仅在于m 和m3 的使用。但是m 和m3 在循环内没有改变。我可以通过交换m 和m3 来简单地消除这个内循环分支吗?
if(st->inverse) { swap(&m, &m3); }
do {
Fout[m].r = scratch[5].r - scratch[4].i;
Fout[m].i = scratch[5].i + scratch[4].r;
Fout[m3].r = scratch[5].r + scratch[4].i;
Fout[m3].i = scratch[5].i - scratch[4].r;
++Fout;
} while (--k);
【问题讨论】:
-
在循环之后,
m和m3会在代码的其他地方使用吗? -
@Someprogrammerdude:公平的问题,但不是。 source。此外,我总是可以把它们换回来。这种优化的驱动力是 1024 点 FFT 对这些 radix-4 蝴蝶执行 5 级,这些内部循环每级运行 256 次。
-
@Someprogrammerdude:在第一个sn-p中
+和-之间的顺序确实不同,但m和m3之间的顺序也不同。那是我的想法背后的驱动力;如果我交换索引(循环外),那么循环内的代码变得相等 -
@Someprogrammerdude:如果
m和m3在else语句中交换并且每组四个语句都进行了排序,则它们是逐字符相同的;+或-没有区别。因此,只有当Fout与scratch重叠时,它们的效果才会有所不同,我预计情况并非如此。 -
@EricPostpischil:正确。 scratch 是一个局部变量,所以编译器可以证明它不重叠。 VS2019 甚至不费心将
scratch[]放入堆栈,它分配了 AVX 寄存器。