Part Number:PROCESSOR-SDK-OMAPL138
假设有两个数组buffA和buffB,分别用在不同的模块中;
当执行拷贝操作时,cache是怎样的变化过程:
for(int i=0;i<n;i++)
buffB[i]=buffA[i];
1、buffA的数据会被从内存缓存到L2、L1D,这个应该比较好理解
2、buffB的数据会被从内存缓存到L2、L1D,然后再被修改为buffA的数据吗?还是说会直接在L1D中构造出cache line数据?
3、如果buffB在复制完成后没有后续操作,使用cache_wbInv是不是会更快的释放cache空间
4、对buffA进行cache_wb操作,然后使用edma对buffA的数据拷贝到buffB,在多大的数据量的情况下会比使用cpu的copy操作更高效?
5、在程序中进行大量数据处理后,如果存在后续不再使用或【一段时间内不再使用】时,使用cache_wbInv、cache_Inv释放该内存范围cache,会不会有效提高其他部分的运行效率?cache_wbInv、cache_Inv操作都需要消耗一定的cpu时间,怎样评估【一段时间内不再使用】的数据是否值得这样操作?这个【一段时间】是怎样的一个时间长度?
Nancy Wang:
Kevin Le82 说:buffB的数据会被从内存缓存到L2、L1D,然后再被修改为buffA的数据吗?还是说会直接在L1D中构造出cache line数据?
建议阅读 1.5 Principle of Locality 跟您举得例子类似
https://www.ti.com.cn/cn/lit/ug/sprug82a/sprug82a.pdf
3、
Kevin Le82 说:使用cache_wbInv是不是会更快的释放cache空间
cache_wbInv、cache_Inv是为了维护缓存一致性
4、不管什么情况,edma都会比cpu访问快
5、
Kevin Le82 说:如果存在后续不再使用或【一段时间内不再使用】时,使用cache_wbInv、cache_Inv释放该内存范围cache,会不会有效提高其他部分的运行效率?
与 3 类似
Kevin Le82 说:cache_wbInv、cache_Inv操作都需要消耗一定的cpu时间,怎样评估【一段时间内不再使用】的数据是否值得这样操作?
是否要执行wb/invalid,取决于这个地址的数据是否还要使用,不是必须执行的操作
,
Kevin Le82:
1.5 Principle of Locality很好的解析了问题1。对于问题2应该和y[]数组对应,文件没有说,我猜想应该是和问题1一致的处理,先缓存,然后修改,否则非cache line对齐的时候,难道还分情况处理不成?
对于问题3,必然是要wb的,否则拷贝数据就没有意义了;拷贝完成后wb,Inv操作对于比较大的内存范围是很消耗时间的;既然数据在本cpu不再操作,使用Inv标记本cache line无效可以避免其他需要的数据由于此cache line未释放而被逐出的问题,应该会提升部分效率。
对于问题4,我的想法是从edma配置、到启动edma执行,再到程序循环判断edma执行完成整个过程所需要的时间,在小数据量的情况下和使用cpu拷贝再wbInv哪个耗时更小。此时buffB的数据通常是给外设或其他cpu使用的。这个【小数据量】的长度就是平衡点,这个长度怎么计算出来?
对于问题5,大量数据操作后,对于不再使用的数据根据需要wbInv、Inv操作应该能提高cache的利用率,但是大范围的内存操作会耗时很久,这个要根据实际情况来处理。对于【一段时间内】不再使用的数据,通常是一个周期性任务使用的数据;此时数据保留在cache与否,取决于任务的频率。我之前再论坛提问了一个问题:在40KHz的一个任务中,第一次进入任务耗时65us,连续执行时(无wbInv、Inv,freeze操作)耗时才17us左右;此时第一次执行的时间就成了一个严重的问题了,目前还没有解决,不知道后续改为进入任务后对数据增加touch操作能否提升效率。
,
Kevin Le82:
目前对于数据cache有touch这个函数,对于代码有类似的函数吗?
,
Tony Tang:
Kevin Le82 说:对于问题5,大量数据操作后,对于不再使用的数据根据需要wbInv、Inv操作应该能提高cache的利用率,但是大范围的内存操作会耗时很久,这个要根据实际情况来处理
Cache wbinv, inv等一致性操作,只有在系统中有EDMA参与数据搬运的情况下才需要考虑使用。不存在清空cache能提高cache使用率的问题。cache的替换是根据最近没使用就替换出去的逻辑自动进行的,不存在Cache满的情况下,新的数据不被Cache的情况,CPU访问新的地址数据时,Cache里的旧数据会被自动替换出去(写回到物理内存上,比如DDR)。一般来说Data cache是2way的,也就是一个数据在cache中可以有两个位置可以存放。这样的好处是数据进了Cache后,是有可能可以存放一段时间的,不会马上被后面的进来的数据给替换掉,从而导致效率很低。
CPU将数据从A copy到B, 只有当用EDMA把B的数据搬走时,需要用Cache wrinv之类的操作来确保数据从Cache写回到B。如果一直是CPU在访问数据,Cache对用户是透明的,不需要操作它,数据都是CPU在处理,不需要在乎它是在Cache里的,还是DDR上的。
,
Kevin Le82:
我的意思是,已经明确不再使用的数据,主动inv,会不会好点;毕竟只有两路,当前这个是最近被访问的,如果此时访问到另外一个地址需要加载时,会把另外的给牺牲掉,而这个已经不再使用的由于刚被访问完而不会被牺牲。
,
Tony Tang:
Kevin Le82 说:目前对于数据cache有touch这个函数,对于代码有类似的函数吗?
没有这个说法吧。为什么会有对代码touch操作这种想法?所谓的touch就是一个连续的循环读一下数据而已。
对于,对于代码可以考虑freeze操作,让频繁调用的函数一直呆在Cache里,以提高效率。
,
Tony Tang:
对了,L2是4 way的。
Kevin Le82 说:已经明确不再使用的数据,主动inv,会不会好点
这个最好是仿真测一下invalid操作需要多少cycle。应该很难一概而论有没有帮助。因为Cache line与物理地址是有映射关系的,要仔细评估一下后面那个数据的访问会替换这个不再用的Buffer.
,
Kevin Le82:
freeze操作之前,怎么保证需要执行的代码已载入cache
,
Tony Tang:
对要freeze的函数做一次主动调用,再freeze。就当做是初始化操作好了。
,
Kevin Le82:
对于函数内存在多个函数调用、有各种条件分支、修改调用参数的函数,主动调用不太好控制cache代码的范围
,
Tony Tang:
代码的地址是固定的,freeze的目的是将频繁调用的函数固定到Cache里,所以你需要先判断哪些函数会被频繁调用,然后主动调用它,这时的调用并不关心它的执行返回结果,只是为了确保代码运行一遍,这样代码就加载到Cache里去了,然后freeze。
比如:
main()
{
funA();
freeze (funA);
funB():
freeze(funB);
xxx
}
这里提供的是一种方法,具体实现根据的代码特点进行调整。
,
Kevin Le82:
我理解你的意思;只是这个需要freeze的函数里面存在比较复杂的分支处理,调用这个函数不能保证全部分支都已经被cahe了;如果有类似touch的函数,将该函数代码都cache了之后freeze就很好了;目前看来没有什么办法可以实现。
另外一个inv操作,每次只能操作64KB左右的数据,其实对于cache来说,他的cache line个数最大基本都是在1024个,如果增加一个函数,传入无效地址+数据长度(32bit位),这样对于cahce器件来说只是遍历一遍1024个数据就可以了;现在对于一个20MB(或更高)以上的内存范围inv时,却需要操作(20*1024)MB / 64KB * 1024 cacheline,数据量大了太多了。