90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
1 | |
OpenCL в Delphi XE2 под Win64bit: можете протестировать на своей видеокарте?21.01.2016, 13:04. Показов 14254. Ответов 44
Метки нет (Все метки)
Суть проблемы. Есть весьма объёмный ПК для научных расчётов: интерфейс, База данных, много-поточные расчёты (на CPU пока), графика 2D, графика 3D на OpenGL, анимация результатов в виде компрессированного avi-файла на выходе - всё делалось на Delphi XE2...XE6 и прекрасно работает. Надо подключить модуль для переноса части длительных фрагментов расчёта на GPU. Этот модуль пытались писать на Visual Studio 2015 - расширение языка C++ AMP, как DLL: работает, но криво: не на всех видеокартах, увы (текст тестовой программы выложен в той же папке для скачивания - см.ниже). Ну и вечная проблема с недостающими DLL к тому что написано на Visual Studio: даже опции компилятора /MT не помогают... На JAVA тоже сейчас мои коллеги пишут этот расчётный модуль - через OpenCL... Ну не в этом вопрос. Есть примеры использования библиотеки OpenCL.dll прямо в проектах Delphi (чехи, например, делали, есть ещё компоненты от MITOV для Delphi Seattle - http://www.mitov.com/ ). Эти несложные примеры работают, но...только при компиляции под Win32, а компилируешь проект Delphi под Win64 - затык...
----- Сейчас вроде с помощью советов с другого форума, удалось траблы победить, и сделать работоспособный тест. ----- Вот ссылка для скачивания: http://gofile.me/2Zesj/C0f3wb1o ======== Там в папке: ======== 1) Полезная утилита GPU_Caps_Viewer_Setup_v1.25.0.0.exe для контроля состояния видеокарты, особенно, если нажать кнопку "More GPU Info". 2) OpenCL1_2_Delphi.zip - файл с примером от чехов (Университет Брно, насколько помню) использования OpenCL в Delphi, 2013год. У меня этот пример не всегда корректно работал при компиляции под Win64 (не на всех видео-картах). Но там хороший заголовочный файл CL.pas - его можно чуть доработать с учётом замечания про NativeInt с другого форума: заменить тип size_t на NativeInt для Win64, и использовать вместо моего "укороченного" MyOpenCL.pas - см.ниже. --- 3) Вложенная папка с моим вариантом программы-теста. Она самодостаточна: больше ничего не надо, ну разве что последние версии видео-драйверов установить. Тест сделан под Delphi XE2 (работает и под XE6). Причём работает, по крайней мере у меня, при компиляции под Win32, и что более важно- под Win64. Всего 2 файла: --> MyOpenCL.pas: заголовочный; я его урезал - убрал ненужные мне функции, которые в принципе можно взять из файла чехов CL.pas + учёл полезное замечание с др.форма про NativeInt ; --> FMain.pas : тестовая программа. Выделяет на GPU память (создаёт буферы) под 16 массивов (квадратных матриц из cl_Float, размер стороны которых задаётся на основной форме, по умолчанию 1200) и под ещё один массив, того же размера, куда пишется результат несложных вычислений на GPU. Потом запускается итерационный цикл (количество итераций - для проверки времени работы - задаётся тоже на форме, по умолчанию - 12). Внутри каждой итерации 16 массивов заполняются данными, затем запускается ещё и внутренний цикл: 30 проходов вызова расчётного ядра на GPU. Такая структура тестовой программы больше всего подходит под наши научные задачи (вычислит. гидродинамика), но пока это лишь тест. В тесте есть несложная проверка правильности вычислений - для одного из элементов матрицы-результата, поскольку НЕ все драйверы видеокарт (особенно старые) могут диагностировать Kernel Error. --> программа на С для ядра - текстовый файл ProgramGPU.CL (должен лежать рядом с MyFirstOpenCL.exe !!): там можно глянуть, что делается с одномерными массивами на GPU. Она прямо передаётся в виде строки на GPU, там копилируется и линкуется - ну как обычно в OpenCL. Нужная DLL для OpenCL - под Win64 или Win32 - подключится из системных папок Windows автоматически, в зависимости от компиляции. ---- 4) Можете на своём сетапе запустить прямо готовый MyFirstOpenCL.exe (это версия 64bit !!) с параметрами: --> размер стороны матрицы = 3200; лезут 17 таких матриц на видеокарту от 1Gb и выше; если не влезут (часть видео-памяти уже занята чем-то - GPU_Caps_Viewer в помощь) - возможны ошибки, которые диагностируются НЕ всем драйверами видеокарт, а только новыми; --> количество итераций (внешний цикл) = 12. --- 5) У меня для указанного примера время счёта вышло: NVIDIA GT-430 (1Gb, 96core, 700MHz core) - 3мин 37сек; NVIDIA GTS-450 (1Gb, 192core, 810MHz core) - 1мин 36сек; NVIDIA GTX-570 (1.28Gb, 480core, 732MHz core) - 42.5сек; AMD Radeon R9 M275X (2Gb, 640core, 925MHz core) - 1мин 27сек - настольный моноблок ASUS 2702. ---- Может кто-то попробовать MyFirstOpenCL.exe на своих видеокартах??? Поскольку это проект дельфовый, никакие внешние DLL ему не нужны (кроме тех что в Windows у всех есть), как и всякие - джава-машины: только для видео-карты новые драйверы желательны. Запустить, нажать верхнюю кнопку на форме, установить размер матрицы 3200 (если 1200 отработает корректно), выбрать платформу-девайс, нажать нижнюю кнопку на форме. Записать время счёта: оно выдаётся в итоговом окне. Нам сейчас на работу надо будет покупать новую карту 4-6Gb именно для расчётов...денег более 60тр вряд ли выделят... AMD конечно подешевле, но... Такие сопоставительные тесты на задачах, приближенных к нашим, были бы полезны!! Были бы полезны и замечания участников форума по тестовой программе. === К сожалению, у меня нет под рукой видео-карты (акселератора) с памятью на борту 4Gb-12Gb. Было бы интересно протестить и на таких "монстрах", повышая понемногу размер входной матрицы (требуемую память тестовая программа сообщит в начале работы): для того и писалось под Win64 - нужна большая память. Буду признателен!
0
|
21.01.2016, 13:04 | |
Ответы с готовыми решениями:
44
Проект на Delphi XE2 под Windows XP OpenGL и невидимый Bitmap: не всякая поверхность строится под Delphi XE2 64bit Поддержка OpenCL AMD на видеокарте ATI Radeon HD 6370M Что можете подсказать по этой видеокарте intel hd video 1274 mb |
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
28.01.2016, 13:54 [ТС] | 21 |
В два раза, если размер массива - простое число. Что на NVIDIA, что на AMD. Выровнял все массивы на длину 32 числа clFloat - всё ОК. Когда попадаю на "фиктивные" элементы массивов в Kernel - просто "return". Почему так влияет на скорость - не знаю. Здесь что-то про это есть: https://www.mql5.com/ru/articles/407
Насколько понял, в память clGlobal тоже не желательно подавать некогерентные (хаотичные) запросы, но это не так критично, как с памятью clLocal (та что для рабочих групп, видимо). Мне приходится опрашивать для каждой расчётной Kernel нити по 16 адресов памяти (на чтение), причём адреса, увы, не рядом. Видимо, не всегда такой "кривой" запрос упаковывается драйвером OpenCL в "волновой-фронт"/warp-канат. Ну хотя бы разные нити в одну и ту же ячейку глобальной памяти GPU за информацией не лезут (или очень редко). === Вчера сравнивал работу AMD Radeon R9 M275X c NVIDIA GTX-450. Действительно, драйвер AMD держит вложенный в Kernel цикл аж втрое длиннее. Постараюсь вообще уйти от подобных циклов. === Вопрос возник. А можно в одной передаваемой на GPU строке-программе сделать внутри сразу 2 Kernel с разными именами? Какие-то директивы надо писать? В лоб не выходит! Может, ткнёте носом в пример? Вот здесь увидел, что даже внешние файлы на C++ можно подключать к программе строке: https://habrahabr.ru/post/146823/ У них первая строка в программе для Kernel: #include "MathCode.cpp" Добавлено через 17 часов 3 минуты В целом, разобрался в причинах. Подсказка здесь: http://stackoverflow.com/quest... -in-opencl Своими словами. Я ранее задавал только общее количество расчётных нитей по каждому измерению: GlobalThreads[0], GlobalThreads[1]. У меня двумерные массивы-потоки-нити: в моей задаче с 2D Threads удобнее. Порядок значений по каждому измерению - 1...4тыс. А вот размеры рабочих групп нитей (микро-блоки, на которые нацело разбиваются Global-потоки-нити) LocalThreads[0], LocalThreads[1] я ранее никак не задавал, т.е. передавал в Kernel вместо указателя на массив @LocalThreads[0] просто nil. Эмпирическим путём выяснил, что максимальное быстродействие на GPU, например, на NVIDIA GTS-450, достигается в моей задаче не для значений LocalThreads[0], LocalThreads[1], которые сам драйвер в этом случае (nil) устанавливает по умолчанию, а при: LocalThreads[0] = 32; LocalThreads[1] = 16. Максимум их произведения не должен превышать для данного устройства-акселератора 32х32 (можно сделать OpenCL-запрос, чтобы для конкретного устройства уточнить этот максимум). Ну и, конечно: - GlobalThreads[0] должен быть кратен LocalThreads[0] ; - GlobalThreads[1] должен быть кратен LocalThreads[1] - иначе выскочит ошибка при выполнении Kernel. Лишние (добавленные для выравнивания-кратности) глобальные потоки-нити делаются "холостыми": просто return из Kernel. В топике по ссылке автор из-за бугра просто заставляет делать их ненужные действия, но подход к ускорению, IMHO, тот же. === С асинхронными вызовами OpenCL команд, т.е. с очередью CommandQyeue типа out-of-order - тоже поигрался. Головоломка, однако! Это фишка OpenCL по сравнению с CUDA. Но работает! Только надо кое-где ставить в программе clEnqueueBarrier(CommandQueue) : иначе из этой "очереди-толкучки" GPU вообще хаотично будет поступившие в неё команды выдёргивать. === А правда, что на картах NVIDIA доступ к функциям OpenCL организован через драйвер CUDA?? Как же тогда не имеющую аналога в CUDA очередь типа out-of-order организовали??
1
|
4175 / 1825 / 218
Регистрация: 06.10.2010
Сообщений: 4,111
|
|
01.02.2016, 16:28 | 22 |
AMD FX-8350 - 7 min 21 sec 839 msc
AMD Radeon 7950 - 1 min 38 sec 967 msc FIL i7-4790K быстрее чем Radeon 7950? А если задействовать всю мощь: AVX2 в 8 потоков? Добавлено через 23 минуты Посмотрел исходник - на AVX2 хорошо ляжет. Инструкция VDPPS выполнит большую часть работы.
0
|
Модератор
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
|
|
01.02.2016, 16:36 | 23 |
Получается что так) По крайней мере на этом тесте.
Думаю зависит от того, на сколько оптимально OpenCL использует мощности процессора. По крайней мере процессор грузится на 100%. Но в любом случае, если переписать алгоритм на асме под AVX2, должно быть еще быстрее.
0
|
1 / 1 / 0
Регистрация: 04.02.2016
Сообщений: 7
|
|
05.02.2016, 17:54 | 24 |
Prok12. Я потестил на своём ноуте, результат во вложении.
Но у меня вопрос по заголовочному файлу, о чём шла речь выше //Но там хороший заголовочный файл CL.pas - его можно чуть доработать с учётом замечания про NativeInt с другого форума: заменить тип size_t на NativeInt для Win64, и использовать вместо моего "укороченного" MyOpenCL.pas \\ В GLScene давно включен переведенный хедер OpenCL, см. http://sourceforge.net/p/glsce... /GLSCL.pas и http://sourceforge.net/p/glsce... LSCLGL.pas Похоже там более полный перевод. Попробуй откомпилировать с этими заголовками.
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
||||||
06.02.2016, 01:16 [ТС] | 25 | |||||
Это устаревший файл - 2011г (даже у чехов по ссылке CL.pas более новый и полный - 2013г), к тому же, без многих описаний типов в начале. Возможно, что-то ещё есть в непредставленном "приложении" к нему {$I cl.inc}. В общем, подключить его "в лоб" не удастся.
=================================== Прикольные там комментарии в тексте:
ps. Сегодня на работе в свой комп установил новую Nvidia GTX-980ti : для указанного нарочито неоптимального теста время сократилось до 22сек (размер матрицы 3200). ==== А пока тут шло тестирование... уже переписал часть "трудоёмкого" кода в своей основной (не тестовой уже) программе на OpenCL, 3 кернела. Сравнительно быстро всё отладил. Предварительный итог: время счёта на задачах (сутками считаются - гидродинамика ) уже сократилось вдвое.
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
06.02.2016, 15:23 [ТС] | 27 |
Это была тестовая программа. В реальной мне приходится работать не с одномерными массивами (векторами), а с двух- и даже трёх-мерными. По-простому в Kernel на GPU двумерный массив не передать: скажем, параметр типа float** MyMatrix компилятор GPU не пережуёт!! Повторюсь: только одномерные массивы, т.е., дух-трёх-мерные приходится "растягивать" на хосте (CPU) в длинный вектор, а внутри самого Kernel на GPU - сворачивать обратно, например, в матрицу уже не с одним индексом n , а с двумя - i,j. Это и была проба!
==== Кстати, на эффективность использования шейдеров GPU очень сильно влияет, как сворачивали двумерный массив в вектор (2 способа) или трёхмерный массив (6 способов). Элементы этого большого 1D массива, к которым обращается Kernel (особенно, в которые пишет результаты) желательно чтобы оказались рядышком. Тогда GPU сможет, образно говоря, "сплести" расчётные нити в так называемые "канаты" - Warp. В противном случае менеджер памяти будет "рыскать" по всей глобальной памяти GPU в поисках необходимого адреса-элемента массива : скорость резко упадёт. Потому в папке для скачивания есть 2 тестовых файла для компилятора GPU: оба с расширением CL - Slow и Fast. Любой их них можно положить рядом с exe-шником, и сравнить время.
1
|
1 / 1 / 0
Регистрация: 04.02.2016
Сообщений: 7
|
|
06.02.2016, 23:02 | 29 |
Prok12
//даже у чехов по ссылке CL.pas более новый и полный - 2013г\\ Посмотрел у чехов, там очень старая не полная версия ещё OpenCL 1.1. Вот залита свежая полностью обновленная конверсия cl.h >> CL.pas для текущей хроносовской версии OpenCL 2.1, см.здесь: http://sourceforge.net/p/glsce... PIs/CL.pas Да, попутный вопрос, используешь ли ты для генерации сеток тетраэдрализацию, типа http://www.wias-berlin.de/software/tetgen/ или у тебя другой подход? Раз уж ты достиг таких успехов (в сокращении вдвое), то приведи код простого варианта для Дельфи на OpenCL 2.1. А то как-то не верится
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
||||||
07.02.2016, 00:21 [ТС] | 30 | |||||
Простого варианта ЧЕГО? Могу свои кернелы выложить: но уже специфичные - под конкретную задачу.
Сетки в основном регулярные. Для генерации нерегулярных (треугольных) использую обычно триангуляцию Делоне.
Добавлено через 2 минуты Явно свежее!! Позавчера появилась:
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
07.02.2016, 00:34 [ТС] | 32 |
... но всё равно не хватает к нему:
uses CL_Platform; и ещё {$I cl.inc}
0
|
1 / 1 / 0
Регистрация: 04.02.2016
Сообщений: 7
|
|
07.02.2016, 08:32 | 33 |
Они в той же папке, в репозитории - кликни на ParallelAPIs и найдешь
http://sourceforge.net/p/glsce... allelAPIs/
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
08.02.2016, 16:29 [ТС] | 34 |
Попробовал их заголовочные файлы: CL.pac, CL_Platform.pas, cl.inc. Пришлось чуток повозиться с наименованиями типов: они "Т" в начале добавили. Плюс надо явным образом вызывать инициализацию OpenCL - вызвать InitOpenCL. Файл inc особой роли не играет. Но! Сходу не пошло: даже список платформ не выдаётся. Всё вместе - в той же ссылке для скачивания в под-папке OpenCL_Demo2016. Если кому интересно - можете попробовать довести до ума!
Там же есть и новый работающий пример: (он по сути тот же, что не пошёл с заголовочником от Khronos) выкинул всё написанное чехами, всё переписал заново, более осмысленно. Две программы-Kernel (используется в тесте первая), контроль погрешности, использование в Kernel функции-atomic. Но Header-файл пока оставил свой. Ещё там же в отдельной по-папке - 2 картинки-скана TIF с моими вопросами по работе новой видяхи GTX-980ti. И наконец, в папке OpenCL_Demo2016 есть под-папка с моими 3-мя Kernel - последний длинный вчера написал и опробовал - можете полюбопытствовать! С этими ядрами уже удалось ускорить исходную программу по сравнению с 6(12)-ти ядерным процем Intel-Extream990 аж в 3 (три) раза: только самый "долгоиграющий" фрагмент кода переписал на OpenCL. Добавлено через 9 минут Вот ссылка только на новую по-папку: http://gofile.me/2Zesj/TOT6JHm0
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
10.02.2016, 20:36 [ТС] | 35 |
====
ПыСы. Посоветуйте, коллеги, на каком форуме активно обсуждается написание самих Kernel для OpenCL (программки на языке, похожем на C99, которые компилирует сам драйвер видео-карты). Или здесь подскажите, как разбивать для Kernel'a большую программу на модули (хотя это в принципе есть в моём новом примере - уже вроде осилил), и главное - как обмениваться между этими модулями (процедурами) данными: только через их списки параметров? Через всю цепочку процедур этот список тащить до той, где они действительно нужны??? Писать весь расчётный модуль одним "монолитом" без разбивки на модули - не кашерно , сами понимаете. А мне сейчас надо запихнуть на GPU код в несколько тысяч строк...
0
|
1 / 1 / 0
Регистрация: 04.02.2016
Сообщений: 7
|
|
11.02.2016, 01:13 | 36 |
https://forums.khronos.org/for... us-systems
1
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
11.02.2016, 07:38 [ТС] | 37 |
Там не так загружаются библиотечные функции из OpenCL.dll. Т.е. после вызова LoadOpenCL загрузка ВСЕХ (зачем они все то, включая ненужные мне, сразу на борт грузят?? ) идёт до конца, но обращаться к ним даже для поиска количества платформ не выходит.
Я начинал работать с графикой на OpenGL для Delphi примерно в 2005, а может и чуть раньше. Ну когда книжка Краснова с таким же названием - Графика OpenGL в проектах Delphi - появилась. Ещё и с ним переписывался. GLScene появилась чуть позднее. Сразу решил не переписывать на её компоненты, а использовать -как и в случае с OpenCL- свой заголовочник к DLL. В итоге уже с появления 64-разрядной Delphi XE2 у меня все проекты отлично собираются под Win64. А с GLScene несколько раз наступал на грабли...
0
|
1 / 1 / 0
Регистрация: 04.02.2016
Сообщений: 7
|
||||||
11.02.2016, 10:25 | 38 | |||||
Загружаются только указатели на функции, например,
Вообще-то GLScene от М.Лишке появилась гораздо раньше, в 1997 году (см., как пример, во вложении). А 64-разрядная GLScene давно существует под Lazarus/Typhon (FPC) для любых платформ. Речь шла об отсутствии рабочей версии для Win64 под RAD Studio, так как в этом случае надо в интерфейсной части библиотеки перейти от VCL к FMX. Переход идёт вяло - основная масса кодеров как крысы с тонущего корабля разбежались кто куда (гл.разработчик Э.Гранж занялся веб.скриптами DWS, русский сайт украинских программистов заглох и т.д.) и стали изобретать собственные кривые лисапеды, вместо того, чтобы заклеить проколы и поднять руль повыше у отличного механизма. А теперь вон на форумах народ мучительно вопрошает - как повращать кубик мышкой в OpenGL?
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
30.12.2017, 15:27 [ТС] | 39 |
Сейчас возник другой вопрос: программное определение загрузки GPU, его памяти, температуры и т.д.
Для NVIDIA у меня это получилось с использованием библиотеки nvml.dll - https://www.cyberforum.ru/delp... 66781.html. А вот с AMD пока туго идёт. Смог только определить загрузку GPU от AMD и его текущую температуру - использовал atiadlxx.dll. Но вот определить, сколько процентов памяти задействовал с карты AMD под свои расчёты на OpenCL пока не смог. C NVIDIA у меня это вышло без проблем (пример есть в соседней ветке форума, по ссылке). Увы, для atiadlxx.dll нет подробного мануала, как для NVIDIA - https://docs.nvidia.com/deploy... _Guide.pdf. Может, вообще нужна для AMD другая DLL - GPUPerfAPIGL.dll для определения загрузки памяти ? А как для AMD загрузку контроллера памяти найти - вообще не знаю. Хорошо бы пример!
0
|
90 / 16 / 1
Регистрация: 08.11.2011
Сообщений: 96
|
|
02.01.2018, 15:56 [ТС] | 40 |
Определение загрузки и температуры GPU типа AMD добавил в пример (ранее всё было только для NVIDIA). Использовал библиотеку atiadlxx.dll. Эта библиотека устанавливается автоматически при установке драйверов видео-карты AMD (у меня это Radeon M275x). Пример перезалил в ту же папку для скачивания http://gofile.me/2Zesj/C0f3wb1o , в ту же уже ранее добавленную под-папку:
OpenCL_Demo2017 Barrier and Local_Memory REDUCT Но вот как определить, сколько памяти на GPU именно AMD уже занято - не разобрался. В стандартных утилитах типа GPU-z 2.5.0 это как-то делается и для AMD тоже : значит, способ есть. Может кто-то подсказать?
0
|
02.01.2018, 15:56 | |
02.01.2018, 15:56 | |
Помогаю со студенческими работами здесь
40
Что можете сказать о видеокарте NVIDIA GeForce GT 610 1024 Мб Что лучше брать Delphi XE2, Delphi XE, Delphi 7? Delphi 2010 feat. Delphi XE2 Перевод из Delphi 7 в Delphi XE2 Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |