Мне любопытно, что такое SIMD, и мне интересно, сможет ли он справиться с этим вариантом использования.
Допустим, у меня есть массив из 2048 целых чисел, например [0x018A, 0x004B, 0x01C0, 0x0234, 0x0098, 0x0343, 0x0222, 0x0301, 0x0398, 0x0087, 0x0167, 0x0389, 0x03F34, 0x00x0]
Обратите внимание, что все они начинаются с 0x00, 0x01, 0x02 или 0x03. Я хочу разделить их на 4 массива:
- Один для всех целых чисел, начинающихся с 0x00
- Один для всех целых чисел, начинающихся с 0x01
- Один для всех целых чисел, начинающихся с 0x02
- Один для всех целых чисел, начинающихся с 0x03
Я предполагаю, что у меня будет такой код:
int main() {
uint16_t in[2048] = ...;
// 4 arrays, one for each category
uint16_t out[4][2048];
// Pointers to the next available slot in each of the arrays
uint16_t *nextOut[4] = { out[0], out[1], out[2], out[3] };
for (uint16_t *nextIn = in; nextIn < 2048; nextIn += 4) {
(*** magic simd instructions here ***)
// Equivalent non-simd code:
uint16_t categories[4];
for (int i = 0; i < 4; i++) {
categories[i] = nextIn[i] & 0xFF00;
}
for (int i = 0; i < 4; i++) {
uint16_t category = categories[i];
*nextOut[category] = nextIn[i];
nextOut[category]++;
}
}
// Now I have my categoried arrays!
}
Я предполагаю, что мой первый внутренний цикл не нуждается в SIMD, это может быть просто инструкция (x & 0xFF00FF00FF00FF00)
, но мне интересно, можем ли мы превратить этот второй внутренний цикл в инструкцию SIMD.
Есть ли какая-нибудь SIMD-инструкция для этого действия по «категоризации», которое я делаю?
Инструкции по «вставке» кажутся несколько многообещающими, но я слишком зелен, чтобы понимать описания на https://software.intel.com/en-us/node/695331.
Если нет, то приближается ли что-нибудь?
Спасибо!
vpconflictd
(например, на KNL, но не на Skylake-avx512) вы сможете выйти вперед. Это похоже на проблему с гистограммой (где вы увеличиваете массив счетчиков для каждого сегмента), но сложнее, потому что на самом деле вам нужно сохранить каждый элемент. - person Peter Cordes   schedule 18.09.2018