Это моя простая функция блинтинга:
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-байтовыми блоками.
Мое узкое место?Понятия не имею, на самом деле, я не думаю, что это строка кэша, поскольку моя частота промахов низкая (?), И 64
(мой размер строки кэша) не имеет особого значения при изменении ситуации.Но я не думаю, что это скорость памяти (поскольку 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
(становящейся функционально идентичным memcpy
) обеспечивает ускорение <1%, даже если: </p>
memcpy
быстрее на ~ 25%.Я хочу максимально приблизиться к скорости необработанных memcpy
, сохранив цвет 0
как прозрачный.
Проблема в том, насколько я знаю, ни одна векторная инструкция не поддерживает условные выражения, но янадо сохранить dest
где src
равно 0
.Есть ли что-нибудь [быстрое], которое может действовать как OR
, но на уровне байтов?
Я читал до того, как появилось расширение или что-то, чтобы сказать ЦПУ не кэшировать некоторые данные, но я не могу найтиэто снова.Моя идея состоит в том, чтобы не читать напрямую из src
, а только записывать из него в dest
и следить за тем, чтобы он не кэшировался.Затем просто прочитайте битовую маску, чтобы проверить прозрачность. Я просто не знаю, как на самом деле это сделать. Возможно ли это, не говоря уже о посте?Я тоже этого не знаю, поэтому и задаю этот вопрос.
Я бы предпочел советы о том, как сделать быстрее только с C, может быть, с некоторыми расширениями gcc, но если сборка x86 - единственный способ, быть по сему.Помочь мне понять мое фактическое узкое место (так как я смущен своими результатами) тоже помогло бы.