Intereting Posts
Два или более типа данных в спецификаторах объявлений ошибка Запись streamа RTSP с помощью FFmpeg libavformat error: неверный аргумент типа ‘унарный *’ (есть ‘int’) scanf не печатает и не читает ничего Как настроить делегат / обратный вызов из DLL (взаимодействие между C и C #) Какие библиотеки зеленых streamов доступны для C, которые могут соответствовать производительности и простоте использования зеленых streamов Haskell? Как работает оператор + в C? Как найти позицию строки внутри другой строки в C рекурсивно? Управлять escape-последовательностями с ncurses? Выполняет ли escape-последовательность printf? UML для языка программирования C Почему использование mod с операндом int64_t делает эту функцию на 150% медленнее? Правила распределения регистров в коде, сгенерированном основными компиляторами C / C ++ gcc не может предупредить о неинициализированной переменной Где я могу найти полную ссылку на API ncurses C? Вложенные аргументы

Матрица Умножение размера 100 * 100 с использованием SSE Intrinsics

int MAX_DIM = 100; float a[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float b[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); float d[MAX_DIM][MAX_DIM]__attribute__ ((aligned(16))); /* * I fill these arrays with some values */ for(int i=0;i<MAX_DIM;i+=1){ for(int j=0;j<MAX_DIM;j+=4){ for(int k=0;k<MAX_DIM;k+=4){ __m128 result = _mm_load_ps(&d[i][j]); __m128 a_line = _mm_load_ps(&a[i][k]); __m128 b_line0 = _mm_load_ps(&b[k][j+0]); __m128 b_line1 = _mm_loadu_ps(&b[k][j+1]); __m128 b_line2 = _mm_loadu_ps(&b[k][j+2]); __m128 b_line3 = _mm_loadu_ps(&b[k][j+3]); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x00), b_line0)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0x55), b_line1)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xaa), b_line2)); result = _mm_add_ps(result, _mm_mul_ps(_mm_shuffle_ps(a_line, a_line, 0xff), b_line3)); _mm_store_ps(&d[i][j],result); } } } 

приведенный выше код, который я сделал для умножения матрицы, используя SSE. код работает как streamи. Я беру 4 элемента из строки из умножения на 4 элемента из столбца из b и перехожу к следующим 4 элементам в строке a и следующих 4 элементов в столбце b

Я получаю ошибку. Ошибка Segmentation fault (core dumped) Я действительно не знаю, почему

Я использую gcc 5.4.0 на ubuntu 16.04.5

Редактирование: segmentation fault была решена _mm_loadu_ps. Также есть что-то не так с логикой, я буду большой, если кто-то поможет мне ее найти

Ошибка сегментации была решена _mm_loadu_ps Также есть что-то не так с логикой …

Вы загружаете 4 перекрывающиеся windows на b[k][j+0..7] . (Вот почему вам нужен loadu ).

Возможно, вы хотели загрузить b[k][j+0] , +4 , +8 , +12 ? Если это так, вы должны выровнять b на 64, так что все четыре загрузки поступают из одной и той же строки кэша (для производительности). Устраничный доступ невелик, но использование всех 64 байтов каждой линии кэша, к которой вы прикасаетесь, намного лучше, чем заставить строку-майора против основного столбца полностью ошибаться в скалярном коде без блокировки.

Я беру 4 элемента из строки из умножения на 4 элемента из столбца из b

Я не уверен, что ваше текстовое описание описывает ваш код.

Если вы уже не транспонировали b , вы не можете загружать несколько значений из одного столбца с нагрузкой SIMD, потому что они не смежны в памяти.

Многомерные массивы C – это «основные строки»: последний индекс – тот, который наиболее быстро изменяется при переходе на следующий адрес более высокой памяти. _mm_loadu_ps(&b[k][j+1]) ли вы, что _mm_loadu_ps(&b[k][j+1]) собирался дать вам b[k+0..3][j+1] ? Если это так, это дубликат умножения матрицы матриц SSE (этот вопрос использует 32-разрядное целое число, а не 32-битное значение float, но то же самое, что и проблема компоновки).


Чтобы отладить это, поместите простой шаблон значений в b[] . подобно

 #include  alignas(64) float b[MAX_DIM][MAX_DIM] = { 0000, 0001, 0002, 0003, 0004, ..., 0100, 0101, 0102, ..., 0200, 0201, 0202, ..., }; // ie for (...) b[i][j] = 100 * i + j; 

Затем, когда вы выполняете свой код в отладчике, вы можете увидеть, какие значения попадают в ваши векторы.

Для ваших значений a[][] , возможно, используйте 90000.0 + 100 * i + j поэтому, если вы смотрите на регистры (вместо переменных C), вы все равно можете указать, какие значения a и b .


Связанные с:

  • Ульрих Дреппер « Каждый программист должен знать о памяти» показывает оптимизированную матрицу с блокировкой кеша с помощью SSE instrinsics для двойной точности. Должна быть легко адаптирована для float .

  • Как BLAS получает такую ​​экстремальную производительность? (Возможно, вы захотите просто использовать оптимизированную библиотеку matmul, настройка matmul для оптимальной блокировки кеша является нетривиальной, но важной)

  • Матричное умножение с блоками
  • Плохая математическая производительность в C vs Python / numpy имеет некоторые ссылки на другие вопросы
  • как оптимизировать матричный умножитель (matmul) для быстрого запуска на одном процессорном ядре