Сообщение Re[22]: .Net на эльбрусах от 19.08.2022 7:43
Изменено 19.08.2022 8:10 vdimas
Re[22]: .Net на эльбрусах
Здравствуйте, 4058, Вы писали:
4>Это показывает, что Intel выполняет этот тест в ~4 раза быстрее Эльбрус
Этот тест показывает, что авторы статьи не потрудились поискать наилучшую стратегию обхода памяти.
Вот наивная реализация умножения матриц:
Это схема ijk.
По классике наилучший результат из наивных даёт схема kji.
У авторов схема kij, которая, увы, является наихудшей.
Не наивной является схема прохода по транспонированной матрице.
Т.е одну из матриц сначала транспонируют, а потом в цикле нижнего уровня итерация проходит у всех трех матриц по 1-му элементу, а не прыгает как кенгуру по памяти.
Далее, операции j*n, i*n (для транспонированной) надо выносить наверх — компилятор С++ не имеет право выносить эти якобы константные для цикла нижнего уровня выражения выше по соображениям многопоточности — вдруг в параллельном потоке данные меняются, а мы и не знаем.
Увы, подобного рода оптимизации для Интела надо делать ручками.
И вот тут-то пресловутая автовекторизация SIMD и срабатывает, т.к. за один такт можно вычислить 4 ячейки, т.е. 4 оборота цикла.
А в Эльбрусе можно указать прагмами, что всё ОК, можно смело оптимизировать, будто это личные данные текущего потока.
Далее, обрати внимание на +=, уупс?
Надо заводить локальную переменную и накапливать результат в ней, а затем писать лишь однажды.
Ты дочитай до конца, автор там поиграл еще и получил на вручную написанной реализации результат примерно вдвое быстрее, чем с помощью EML, т.е. в 200 раз быстрее от исходного варианта.
А для Интел как ни крути — ничего уже особо не накрутишь.
4>при этом уступает в 20-ть раз тесту с использованием eml.
При этом eml ускорила наихудший вариант вычислений в 100 раз.
4>Это такая-же нелепость как сравнивать перемножение матриц с использованием SIMD и без него.
С чего ты решил, что SIMD не используется?
Компилятор компиллирует с SIMD инструкциями в любом случае.
Особенно хорошо для матриц.
Просто SIMD бывает очень разный.
Просто надо правильно обходить память, чтоы какие надо SIMD инструкции подставлялись.
4>В данном случае было бы интересно сравнить результаты с использованием упомянутого в статье MKL от Intel.
MKL даёт прирост от наихудшей наивной реализации в ~10 раз.
Сравни с ускорением в 200 раз на Эльбрусе.
В общем, у этой архитектуры есть характеристика — флопсы на такт.
Необходимо в реализации софта поднимать эту характеристику на максимум (т.е. загружать максимальное кол-во исполнительных блоков в каждом такте), чтобы Эльбрус показывал себя во всей красе.
4>Это показывает, что Intel выполняет этот тест в ~4 раза быстрее Эльбрус
Этот тест показывает, что авторы статьи не потрудились поискать наилучшую стратегию обхода памяти.
Вот наивная реализация умножения матриц:
for(i = 0 i < n; i++ )
for(j = 0; j < n; j++ )
for(k = 0; k < n; k++ )
C[j * n + i] += A[j * n + k] * B[k * n + i];
Это схема ijk.
По классике наилучший результат из наивных даёт схема kji.
У авторов схема kij, которая, увы, является наихудшей.
Не наивной является схема прохода по транспонированной матрице.
Т.е одну из матриц сначала транспонируют, а потом в цикле нижнего уровня итерация проходит у всех трех матриц по 1-му элементу, а не прыгает как кенгуру по памяти.
Далее, операции j*n, i*n (для транспонированной) надо выносить наверх — компилятор С++ не имеет право выносить эти якобы константные для цикла нижнего уровня выражения выше по соображениям многопоточности — вдруг в параллельном потоке данные меняются, а мы и не знаем.
Увы, подобного рода оптимизации для Интела надо делать ручками.
И вот тут-то пресловутая автовекторизация SIMD и срабатывает, т.к. за один такт можно вычислить 4 ячейки, т.е. 4 оборота цикла.
А в Эльбрусе можно указать прагмами, что всё ОК, можно смело оптимизировать, будто это личные данные текущего потока.
Далее, обрати внимание на +=, уупс?
Надо заводить локальную переменную и накапливать результат в ней, а затем писать лишь однажды.
Ты дочитай до конца, автор там поиграл еще и получил на вручную написанной реализации результат примерно вдвое быстрее, чем с помощью EML, т.е. в 200 раз быстрее от исходного варианта.
А для Интел как ни крути — ничего уже особо не накрутишь.
4>при этом уступает в 20-ть раз тесту с использованием eml.
При этом eml ускорила наихудший вариант вычислений в 100 раз.
4>Это такая-же нелепость как сравнивать перемножение матриц с использованием SIMD и без него.
С чего ты решил, что SIMD не используется?
Компилятор компиллирует с SIMD инструкциями в любом случае.
Особенно хорошо для матриц.
Просто SIMD бывает очень разный.
Просто надо правильно обходить память, чтоы какие надо SIMD инструкции подставлялись.
4>В данном случае было бы интересно сравнить результаты с использованием упомянутого в статье MKL от Intel.
MKL даёт прирост от наихудшей наивной реализации в ~10 раз.
Сравни с ускорением в 200 раз на Эльбрусе.
В общем, у этой архитектуры есть характеристика — флопсы на такт.
Необходимо в реализации софта поднимать эту характеристику на максимум (т.е. загружать максимальное кол-во исполнительных блоков в каждом такте), чтобы Эльбрус показывал себя во всей красе.
Re[22]: .Net на эльбрусах
Здравствуйте, 4058, Вы писали:
4>Это показывает, что Intel выполняет этот тест в ~4 раза быстрее Эльбрус
Этот тест показывает, что авторы статьи не потрудились поискать наилучшую стратегию обхода памяти.
Вот наивная реализация умножения матриц:
Это схема ijk.
По классике наилучший результат из наивных даёт схема kji.
У авторов схема kij, которая, увы, является наихудшей.
Не наивной является схема прохода по транспонированной матрице.
Т.е одну из матриц сначала транспонируют, а потом в цикле нижнего уровня итерация проходит у всех трех матриц по 1-му элементу, а не прыгает как кенгуру по памяти.
Далее, операции j*n, i*n (для транспонированной) надо выносить наверх, и вот тут-то пресловутая автовекторизация SIMD и срабатывает, т.к. за один такт можно вычислить 4 ячейки, т.е. 4 оборота цикла.
Далее, обрати внимание на +=.
Надо заводить локальную переменную и накапливать результат в ней, а затем писать лишь однажды.
Ты дочитай до конца, автор там поиграл еще и получил на вручную написанной реализации результат примерно вдвое быстрее, чем с помощью EML, т.е. в 200 раз быстрее от исходного варианта.
А для Интел как ни крути — ничего уже особо не накрутишь.
4>при этом уступает в 20-ть раз тесту с использованием eml.
При этом eml ускорила наихудший вариант вычислений в 100 раз.
4>Это такая-же нелепость как сравнивать перемножение матриц с использованием SIMD и без него.
С чего ты решил, что SIMD не используется?
Компилятор компиллирует с SIMD инструкциями в любом случае.
Особенно хорошо для матриц.
Просто SIMD бывает очень разный.
Просто надо правильно обходить память и раскручивать циклы, чтобы какие надо SIMD инструкции подставлялись.
4>В данном случае было бы интересно сравнить результаты с использованием упомянутого в статье MKL от Intel.
MKL даёт прирост от наихудшей наивной реализации в ~10 раз.
Сравни с ускорением в 200 раз на Эльбрусе.
В общем, у этой архитектуры есть характеристика — флопсы на такт.
Необходимо в реализации софта поднимать эту характеристику на максимум (т.е. загружать максимальное кол-во исполнительных блоков в каждом такте), чтобы Эльбрус показывал себя во всей красе.
Капризная штука, да? ))
Компилятор надо развивать нон-стоп, ес-но, на него вся надежда.
Но что здесь внушает оптимизм — при улучшении компилятора можно перепрогонять им софт и получать профит, не меняя ни исходники, ни железо.
4>Это показывает, что Intel выполняет этот тест в ~4 раза быстрее Эльбрус
Этот тест показывает, что авторы статьи не потрудились поискать наилучшую стратегию обхода памяти.
Вот наивная реализация умножения матриц:
for(i = 0 i < n; i++ )
for(j = 0; j < n; j++ )
for(k = 0; k < n; k++ )
C[j * n + i] += A[j * n + k] * B[k * n + i];
Это схема ijk.
По классике наилучший результат из наивных даёт схема kji.
У авторов схема kij, которая, увы, является наихудшей.
Не наивной является схема прохода по транспонированной матрице.
Т.е одну из матриц сначала транспонируют, а потом в цикле нижнего уровня итерация проходит у всех трех матриц по 1-му элементу, а не прыгает как кенгуру по памяти.
Далее, операции j*n, i*n (для транспонированной) надо выносить наверх, и вот тут-то пресловутая автовекторизация SIMD и срабатывает, т.к. за один такт можно вычислить 4 ячейки, т.е. 4 оборота цикла.
Далее, обрати внимание на +=.
Надо заводить локальную переменную и накапливать результат в ней, а затем писать лишь однажды.
Ты дочитай до конца, автор там поиграл еще и получил на вручную написанной реализации результат примерно вдвое быстрее, чем с помощью EML, т.е. в 200 раз быстрее от исходного варианта.
А для Интел как ни крути — ничего уже особо не накрутишь.
4>при этом уступает в 20-ть раз тесту с использованием eml.
При этом eml ускорила наихудший вариант вычислений в 100 раз.
4>Это такая-же нелепость как сравнивать перемножение матриц с использованием SIMD и без него.
С чего ты решил, что SIMD не используется?
Компилятор компиллирует с SIMD инструкциями в любом случае.
Особенно хорошо для матриц.
Просто SIMD бывает очень разный.
Просто надо правильно обходить память и раскручивать циклы, чтобы какие надо SIMD инструкции подставлялись.
4>В данном случае было бы интересно сравнить результаты с использованием упомянутого в статье MKL от Intel.
MKL даёт прирост от наихудшей наивной реализации в ~10 раз.
Сравни с ускорением в 200 раз на Эльбрусе.
В общем, у этой архитектуры есть характеристика — флопсы на такт.
Необходимо в реализации софта поднимать эту характеристику на максимум (т.е. загружать максимальное кол-во исполнительных блоков в каждом такте), чтобы Эльбрус показывал себя во всей красе.
Капризная штука, да? ))
Компилятор надо развивать нон-стоп, ес-но, на него вся надежда.
Но что здесь внушает оптимизм — при улучшении компилятора можно перепрогонять им софт и получать профит, не меняя ни исходники, ни железо.