OSDev

для всех
Текущее время: 21 дек 2024, 20:23

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 4 ] 
Автор Сообщение
СообщениеДобавлено: 01 апр 2015, 17:22 
Аватара пользователя

Зарегистрирован: 17 фев 2013, 16:13
Сообщения: 163
Здесь под выравниванием имеется в виду выравнивание по 16 байт.

Насколько важно для использования SIMD инструкций на ARM выравнивать данные? Есть ли разница в скорости между чтением выровненных или не выровненных данных?

Я использую, например функцию GLKMatrix4Multiply, но совершенно не ясно, где в ней учитывается то, что данные выровнены или не выровнены. Код этой функции (или аналогичной) я нашёл на Хабре. Если я точно знаю, что матрицы выровнены, то какую функцию мне использовать вместо GLKMatrix4Multiply? Или что поменять в указанном исходном коде, чтобы он считывал данные как выровненные? Мне, естественно, нужны Intrinsic-функции, без ассемблера.

Благодарю.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 01 апр 2015, 17:55 
Аватара пользователя

Зарегистрирован: 17 фев 2013, 16:13
Сообщения: 163
Вот кусок кода из самой библиотеки. Не пойму, где здесь указание на то, что данные выровнены.

Код:
    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;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 01 апр 2015, 18:15 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1426
Я с SIMD-инструкциями и всем таким прочим вычислительным дела не имел. Могу предположить две вещи:

1) Требование к выравниванию является обязательным и при его нарушении работать не будет вообще (будет кидать т.н. Data Abort). Такая практика была в ранних версиях архитектуры, включая ARMv4 и, кажется, ARMv5 (лениво искать доку и смотреть, если честно), для обычных операций над целочисленными полусловами и словами; естественно, тогда она распространялась и на вещественные данные, если у проца был соответствующий сопроцессор (а он был редкостью). Позднее требование к всенепременному выравниванию отменили: контроль может быть включен с помощью специального бита, но по умолчанию допускаются невыровненные доступы для почти всех команд собственно процессора -- но насчёт сопроцессоров не в курсе.

2) Даже если невыровненные доступы не запрещены, падение скорости будет, скорей всего, очень заметным. АРМы не отличаются слишком хорошей микроархитектурой, они по сравнению с интеловскими процами весьма примитивны (речь не о системе команд, а именно о микроархитектуре), и я очень глубоко сомневаюсь, что они умеют без лишних тактов ожидания обрабатывать невыровненные данные даже в том случае, если они целиком находятся в одной строке кэша.

Как следствие -- думаю, надо всегда выравнивать все SIMD-данные на границу 16 байтов, ну а прочие -- на их естественные границы, и не заморачиваться тем, есть контроль в библиотечных функциях или нет. Более того, в них контроля быть как бы и не должно, ведь это замедлит работу самих функций. Для управления выравниванием есть прагмы и атрибуты, но они уже зависят от конкретного компилятора.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 01 апр 2015, 23:27 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Когда в строке параметров компилятора указан процессор с поддержкой SSE или указан параметр -sse, то почти всё выравнивается на 16. Стек и начала структур данных выравниваются точно.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB