Вы можете попробовать сделать это с SSE, увеличивая 4 элемента за итерацию.
Предупреждение: за непроверенным кодом следует...
#include <stdint.h>
#include <emmintrin.h>
uint32_t bit_counter[64] __attribute__ ((aligned(16)));
// make sure bit_counter array is 16 byte aligned for SSE
void Count_SSE(uint64 bits)
{
const __m128i inc_table[16] = {
_mm_set_epi32(0, 0, 0, 0),
_mm_set_epi32(0, 0, 0, 1),
_mm_set_epi32(0, 0, 1, 0),
_mm_set_epi32(0, 0, 1, 1),
_mm_set_epi32(0, 1, 0, 0),
_mm_set_epi32(0, 1, 0, 1),
_mm_set_epi32(0, 1, 1, 0),
_mm_set_epi32(0, 1, 1, 1),
_mm_set_epi32(1, 0, 0, 0),
_mm_set_epi32(1, 0, 0, 1),
_mm_set_epi32(1, 0, 1, 0),
_mm_set_epi32(1, 0, 1, 1),
_mm_set_epi32(1, 1, 0, 0),
_mm_set_epi32(1, 1, 0, 1),
_mm_set_epi32(1, 1, 1, 0),
_mm_set_epi32(1, 1, 1, 1)
};
for (int i = 0; i < 64; i += 4)
{
__m128i vbit_counter = _mm_load_si128(&bit_counter[i]);
// load 4 ints from bit_counter
int index = (bits >> i) & 15; // get next 4 bits
__m128i vinc = inc_table[index]; // look up 4 increments from LUT
vbit_counter = _mm_add_epi32(vbit_counter, vinc);
// increment 4 elements of bit_counter
_mm_store_si128(&bit_counter[i], vbit_counter);
} // store 4 updated ints
}
Как это работает: по сути, все, что мы здесь делаем, это векторизация исходного цикла, так что мы обрабатываем 4 бита на итерацию цикла вместо 1. Таким образом, теперь у нас есть 16 итераций цикла вместо 64. Для каждой итерации мы загружаем 4 бита из bits
, затем использовать их в качестве индекса в LUT, который содержит все возможные комбинации 4 приращений для текущих 4 бит. Затем мы добавляем эти 4 приращения к текущим 4 элементам bit_counter.
Количество загрузок, хранилищ и добавлений уменьшено в 4 раза, но это будет несколько компенсировано загрузкой LUT и прочими служебными операциями. Тем не менее, вы все еще можете увидеть 2-кратное ускорение. Мне было бы интересно узнать результат, если вы решите попробовать.
person
Paul R
schedule
17.10.2011
Count
красивее:for(int i=0; i < 64; ++i) bit_counter[i] += (bits >> i) & 1;
. - person Xeo   schedule 17.10.2011gcc 4.2
иLLVM
- person the wolf   schedule 18.10.2011