static void blit8(unsigned char* dest, unsigned char* src)
{
byte i;
for (i = 0; i < 8; ++i) {
if (*src != 0) {
*dest = *src;
}
++dest;
++src;
}
}
我已经使用了
-O3
,并且blit8
被内联了。在这里使用restrict
(gcc)没有效果,在指针中使用不同的递增方式、使用另一个数字作为透明度或使用其他类型代替i
也无法改善情况……我甚至尝试传递一个1字节的位掩码并检查其是否比解引用src
更快。将i
的限制提高到16似乎可以提供一个非常小的速度提升(~4-6%),但我处理的是8字节而不是16字节的块。
我的瓶颈?实际上我不知道,我认为这不是缓存行问题,因为我的miss率很低(?),而当改变一些东西时,64
(我的cache line大小)没有特殊意义。但我也不认为这是内存速度的问题(因为memcpy
更快,稍后会详细介绍)。
cg_annotate
关于blit8
(未内联)的报告如下:
Ir I1mr ILmr Dr D1mr DLmr Dw D1mw DLmw file:function
3,747,585,536 62 1 1,252,173,824 2,097,653 0 674,067,968 0 0 ppu.c:blit8.constprop.0
常规的cachegrind
输出(包含内联函数):
I refs: 6,446,979,546
I1 misses: 184,752
LLi misses: 22,549
I1 miss rate: 0.00%
LLi miss rate: 0.00%
D refs: 2,150,502,425 (1,497,875,135 rd + 652,627,290 wr)
D1 misses: 17,121,968 ( 2,761,307 rd + 14,360,661 wr)
LLd misses: 253,685 ( 70,802 rd + 182,883 wr)
D1 miss rate: 0.8% ( 0.2% + 2.2% )
LLd miss rate: 0.0% ( 0.0% + 0.0% )
LL refs: 17,306,720 ( 2,946,059 rd + 14,360,661 wr)
LL misses: 276,234 ( 93,351 rd + 182,883 wr)
LL miss rate: 0.0% ( 0.0% + 0.0% )
0.8%
的D1缺失率?听起来对我来说相当低。
但是最有趣的是,删除0
-check(变得与memcpy
功能上相同)可以提供小于1%的加速,尽管:
memcpy
快约25%。我希望尽可能接近原始memcpy
的速度,同时保留颜色0
为透明。
问题在于,据我所知,没有矢量指令支持条件语句,但我需要保留src
为0
时的dest
。有什么[快速]可以像按字节级别的OR
一样工作的东西吗?
我之前看过一个扩展或者CPU不缓存某些数据的东西,但我现在找不到它了。我的想法是不直接从src
读取,只从中写入dest
,并确保它不被缓存。然后只需从位掩码中读取以检查透明度。 我不知道如何实际操作。那是否可能快速完成?我也不知道,因此我才会问这个问题。
我更喜欢用C做得更快的提示,也许使用一些gcc扩展,但如果x86汇编是唯一的方法,那就这样吧。帮助我理解我的真正瓶颈(因为我对结果感到困惑)也会有所帮助。
memcpy
函数。 - Weather Vanepblendvb
指令,似乎很适合这里。 - interjay