缓存优化理论
Cache Optimization Theory
我正在考虑重记忆缓存优化,并且喜欢有一些反馈。考虑此示例:
class example
{
float phase1;
float phaseInc;
float factor;
public:
void process(float* buffer,unsigned int iSamples)//<-high prio audio thread
{
for(unsigned int i = 0; i < iSamples; i++)// mostly iSamples is 32
{
phase1 += phaseInc;
float f1 = sinf(phase1);//<-sinf is just an example!
buffer[i] = f1*factor;
}
}
};
优化想法:
void example::process(float* buffer,unsigned int iSamples)
{
float stackMemory[3];// should fit in L1
memcpy(stackMemory,&phase1,sizeof(float)*3);// get all memory at once
for(unsigned int i = 0; i < iSamples; i++)
{
stackMemory[0] += stackMemory[1];
float f1 = sinf(stackMemory[0]);
buffer[i] = f1*stackMemory[2];
}
memcpy(&phase1,stackMemory,sizeof(float)*1);// write back only changed mameory
}
请注意,实际样品循环将包含数千个操作。因此,堆叠式符号可能会变得很大。我认为它不会比32KB更多(那里有较小的L1吗?)
在此堆栈记录中,使用的变量的顺序是否存在?我希望不要,因为我想订购它们,以便可以降低写入大小。还是L1缓存具有与RAM具有相同的缓存行为?
我有一种感觉,我以某种方式做了预摘要的作品,但是我读到的有关预购的只是对如何有效使用它相对模糊。尝试和错误不是5000多行代码的选项。
代码将在Win,Mac和iOS上运行。任何手臂&lt; -> Intel问题会期望吗?
,由于所有内存都可以访问并转移到循环的第一次迭代中,因此这种优化是否无用?
感谢您的任何提示和想法。
起初,我认为由于额外的内存访问和memcpy
所需的指示,第二个很有可能会慢一点,而第一个可以直接与这三个合作使用班级成员已经加载到寄存器中。
尽管如此,我还是尝试使用-O2
和-O3
中的GCC 5.2中的代码摆弄,发现,无论我尝试什么,我都得到了两者的相同汇编指令。考虑到memcpy
通常必须做的所有额外概念工作,这显然被压制到Zilch。
在某些情况下,在某些编译器上,我可以想到您的第二个版本可能更快的速度,即是否涉及访问this->data_member
的混叠,干扰了优化,并导致冗余负载和存储到寄存器。p>在这种情况下,它与L1缓存无关,以及与编译器侧的寄存器分配有关的一切。当您加载相同的内存(成员变量)时,缓存在很大程度上是无关紧要的,无论数据的连续块,它都与寄存器有关。尽管如此,我找不到一个单一的情况,我可以在编译器在一个方案中与另一个情况相比,我测试的每种情况都会产生相同的结果。在一个足够复杂的现实世界中,也许有区别。
然后,在这种情况下,它应该在更安全的一面,简单地做:
void process(float* buffer,unsigned int iSamples)
{
const float pi = phaseInc;
const float p1 = phase1;
const float fact = factor;
for(unsigned int i = 0; i < iSamples; i++)
{
phase1 += pi;
float f1 = sinf(p1);
buffer[i] = f1*fact;
}
}
无需使用memcpy
跳过箍即可将结果存储到阵列和返回中。即使在我的发现中,优化器设法消除了通常相关的开销。
我意识到您的示例是简化的,但是无论您处理多少数据成员,都不需要将结构降低到这样的原始数组(除非这样的数组实际上是最方便的表示)。从性能的角度来看,编译器将有一个"更轻松"的时间(即使今天的优化器非常出色并可以处理),如果您只使用本地变量而不是 memcpy
汇总数据成员进出的数组。<<<<<<<<<<<<<<<<<<<</p>
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- gcc 如何优化此循环?
- 如何防止 CUDA-GDB 中的<优化输出>值
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- const 是否允许在这里进行(理论)优化?
- 缓存优化理论