OSDev http://osdev.su/ |
|
Вопрос про выравнивание памяти для SIMD на ARM http://osdev.su/viewtopic.php?f=7&t=1071 |
Страница 1 из 1 |
Автор: | Zealint [ 01 апр 2015, 17:22 ] |
Заголовок сообщения: | Вопрос про выравнивание памяти для SIMD на ARM |
Здесь под выравниванием имеется в виду выравнивание по 16 байт. Насколько важно для использования SIMD инструкций на ARM выравнивать данные? Есть ли разница в скорости между чтением выровненных или не выровненных данных? Я использую, например функцию GLKMatrix4Multiply, но совершенно не ясно, где в ней учитывается то, что данные выровнены или не выровнены. Код этой функции (или аналогичной) я нашёл на Хабре. Если я точно знаю, что матрицы выровнены, то какую функцию мне использовать вместо GLKMatrix4Multiply? Или что поменять в указанном исходном коде, чтобы он считывал данные как выровненные? Мне, естественно, нужны Intrinsic-функции, без ассемблера. Благодарю. |
Автор: | Zealint [ 01 апр 2015, 17:55 ] |
Заголовок сообщения: | Re: Вопрос про выравнивание памяти для SIMD на ARM |
Вот кусок кода из самой библиотеки. Не пойму, где здесь указание на то, что данные выровнены. Код: float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft;
float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight; float32x4x4_t m; m.val[0] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[0], 0)); m.val[1] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[1], 0)); m.val[2] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[2], 0)); m.val[3] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[3], 0)); m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[0], 1)); m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[1], 1)); m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[2], 1)); m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[3], 1)); m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[0], 2)); m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[1], 2)); m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[2], 2)); m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[3], 2)); m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[0], 3)); m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[1], 3)); m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[2], 3)); m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[3], 3)); return *(GLKMatrix4 *)&m; |
Автор: | SII [ 01 апр 2015, 18:15 ] |
Заголовок сообщения: | Re: Вопрос про выравнивание памяти для SIMD на ARM |
Я с SIMD-инструкциями и всем таким прочим вычислительным дела не имел. Могу предположить две вещи: 1) Требование к выравниванию является обязательным и при его нарушении работать не будет вообще (будет кидать т.н. Data Abort). Такая практика была в ранних версиях архитектуры, включая ARMv4 и, кажется, ARMv5 (лениво искать доку и смотреть, если честно), для обычных операций над целочисленными полусловами и словами; естественно, тогда она распространялась и на вещественные данные, если у проца был соответствующий сопроцессор (а он был редкостью). Позднее требование к всенепременному выравниванию отменили: контроль может быть включен с помощью специального бита, но по умолчанию допускаются невыровненные доступы для почти всех команд собственно процессора -- но насчёт сопроцессоров не в курсе. 2) Даже если невыровненные доступы не запрещены, падение скорости будет, скорей всего, очень заметным. АРМы не отличаются слишком хорошей микроархитектурой, они по сравнению с интеловскими процами весьма примитивны (речь не о системе команд, а именно о микроархитектуре), и я очень глубоко сомневаюсь, что они умеют без лишних тактов ожидания обрабатывать невыровненные данные даже в том случае, если они целиком находятся в одной строке кэша. Как следствие -- думаю, надо всегда выравнивать все SIMD-данные на границу 16 байтов, ну а прочие -- на их естественные границы, и не заморачиваться тем, есть контроль в библиотечных функциях или нет. Более того, в них контроля быть как бы и не должно, ведь это замедлит работу самих функций. Для управления выравниванием есть прагмы и атрибуты, но они уже зависят от конкретного компилятора. |
Автор: | Himik [ 01 апр 2015, 23:27 ] |
Заголовок сообщения: | Re: Вопрос про выравнивание памяти для SIMD на ARM |
Когда в строке параметров компилятора указан процессор с поддержкой SSE или указан параметр -sse, то почти всё выравнивается на 16. Стек и начала структур данных выравниваются точно. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |