На четвертый день появления кода в 2024 году возникла проблема: вам нужно определить, сколько строк «XMAS» содержится в сетке символов, например
MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX
Я решил эту проблему, загрузив все 32 символа 8 возможных направлений, начиная с X, в регистр SIMD и сравнив его с маской.
Это сработало и относительно быстро (она достигла 460 МБ/с, когда я увеличил размер входного файла, чтобы проверить его предел), но если говорить о наших решениях на сервере Discord, на котором много разработчиков и несколько более 15 лет профессионального опыта, рассказал один из них Я считаю, что для этой конкретной проблемы использование инструкций SIMD не может заставить код работать быстрее, и сам лежащий в основе алгоритм более важен.
Поэтому мне интересно, в каких ситуациях стоит ли SIMD? Как распознать ситуацию, когда использование инструкций SIMD может иметь заметное значение? Я думал, что сравнение всех 32 символов в одной инструкции будет иметь большое значение вместо вложения двух циклов for, но, возможно, я ошибался?
typedef struct {
std::vector chars;
uint32_t line_length;
} Data;
Data readFile() {
std::ifstream file("./input/day4_input.txt", std::ios::binary | std::ios::ate);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector buffer(size);
file.read(buffer.data(), size);
file.close();
uint32_t line_length = std::ranges::find(buffer, '\n') - buffer.begin();
buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end());
Data input_data { buffer, line_length };
return input_data;
}
int main(int argc, char** argv) {
Data idata = readFile();
auto coordsToIdx = [&idata] (uint32_t i, uint32_t j) -> uint32_t { return i*idata.line_length + j; };
auto idxToCoords = [&idata] (uint32_t idx) -> std::pair {
return std::make_pair(static_cast(idx / idata.line_length), static_cast(idx % idata.line_length));
};
unsigned int res = 0;
const __m256i _mask = _mm256_setr_epi8(
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S',
'X', 'M', 'A', 'S'
);
std::array out_buff;
for(size_t i = 0; i < idata.chars.size(); i++) {
if(idata.chars != 'X') continue;
char buff[32] = {0};
std::pair coords = idxToCoords(i);
bool u = coords.first >= 3;
bool d = coords.first = 3;
bool r = coords.second
Подробнее здесь: https://stackoverflow.com/questions/792 ... ffectively
Как эффективно использовать SIMD? ⇐ C++
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение