Комментировать

Итак, опишу некоторые

Итак, опишу некоторые результаты которые я получил.
Сразу говорю, что времени на всё не хватает, помимо диплома есть ещё и работа.
Задача которую я решал(точнее использованный метод) - МКЭ.
Метод решения СЛАУ - метод сопряжённых градиентов с preconditioner Якоби.(почему-то попадалась литература на английском языке, как точно переводится этот термин не знаю.. может предобуславливатель.. может всё целиком метод Якоби.. хотелось бы найти нормальное описание на русском)
Так как полученные результаты скорости нужно с чем-то сравнить, причём сравнивать с собственной программой для CPU не культурно(вот, смотрите, 1000 кратное увлечение скорости, по сравнению с наивной CPU реализацией), решил сравнить результат с AnSys'ом(в нём есть JCG, причём выводится подробная информация - сколько итераций, сколько MFlops на SPMV достигнуто). В связи с этим нужно использовать одинаковые конечные элементы. AnSys позволяет создавать новые типы элементов(либо через DLL, либо через статическую(!!! - exe'шник AnSys'а перелинковывается) линковку), но прежде чем кидаться в бой, решил проверить тот элемент, который у меня был - двухмерный треугольник с двумя степенями свободы в узлах, плоское-напряжение. Выяснилось, что в AnSys'е есть точно такой же элемент - PLANE42(я сравнивал матрицы жёсткости - нашёл около пяти способов достать матрицы жёсткости из AnSys).
Размерность задачи - 3000000 степеней свободы(включая граничные условия), причём в AnSys'е там где опора из глобальной матрицы жёсткости вычёркивается строка и столбец , а я, к сожалению, когда писал поставил в этом месте на диагональ большое число, переделывать нет времени, может после сдачи займусь(то есть у меня размерность СЛАУ больше на число опёртых степеней свободы - на 2000).
По поводу double, и single вычислений - single не на много быстрее чем double(за счёт того, что помимо самих матриц и векторов, есть ещё служебная информация о структуре матрицы), а сходится очень медленно, я считаю что нету смысла даже начинать single.
Оптимизацию ядра SPMV делал под double вычисления, причём матрица хранится во float, а вектора и промежуточные данные в double (назовём это SD - SingleDouble)- это связанно с тем, что обычно данные на основе которых формируется матрица жёсткости достаточно неточные, вряд ли есть смысл использовать double. Сделал это для экономии bandwidth, так как SPMV целиком зависит от неё.
Хотя ядра не оптимизировал под SS и DD, результаты приведу.
Тестовая платформа:
Asus P6T, 3xDDR3-1333 2GiB (SisSoftware Sandra показывает 22.8 Гб/c), Core I7 930(включены HT и TurboBoost), GTX480, Windows 2008R2
В Ansys'е включено 8 потоков(по сравнению с одним, очень маленький прирост, около 10%, наверно в связи с тем, что Bandwidth важнее для SPMV. А также с TurboBoost и SmartCache у Core I7).
Количество итераций в секунду(Iter/S): 11.5
GFlop/s(только SPMV): 1.31
Результаты моей программы:

Тип матрицы и векторов Iter/s GFlop/s Эффективное GiB/s Flops ускорение Iter/S ускорение
Single Double 118.18 17.22 130.97 13.15 10.28
Double Double 94.11 11.65 110.35 8.89 8.18
Single Single 141.58 19.22 110.36 14.67 12.31

Причём я знаю ряд улучшений которые можно сделать, для увеличения скорости процентов на 30% при текущем алгоритме. Либо получить где-то 3х(оптимистично, но пока кажется выполнимым, так как планируется в большей степени нагрузить GPU вычислениями) при смене общей концепции.
Важно отметить, что используя не оптимизированные ядра, можно получить раза в 2.5 меньшую скорость(как было у меня в начале).
Также, посмотрев существующие реализации CG на GPGPU, увидел много недостатков. Одна из причин в следующем: итерация CG состоит из серии шагов, причём в некоторых местах выход одного шага сразу используется на следующем, в итоге лучше реализовывать ядра, которые делают сразу несколько шагов, а не тасовать данные в global mem и обратно.