Страницы

Поиск по вопросам

Показаны сообщения с ярлыком opencl. Показать все сообщения
Показаны сообщения с ярлыком opencl. Показать все сообщения

понедельник, 2 марта 2020 г.

Какую лучше архитектуру использовать для вычислений на GPU

#cpp #cuda #gpu #opencl


Необходимо перенести вычисления с CPU на GPU. Начал гуглить про это всё, в итоге
есть 2 похожие архитектуры - CUDA от Nvidia и OpenCL от AMD, второе можно и на Nvidia
использовать. Вроде бы пишут, что видеокарты на AMD больше заточены под вычисления
и быстрее на 30-40%.

У кого был опыт программирования на подобном. Можете прояснить пожалуйста, что лучше
выбрать для себя?

Программу пишу на C#, но как понял, класс вычислений придется писать на C++ и подключать
библиотеку к своей программе.
    


Ответы

Ответ 1



Занимаюсь сложными гидродинамическими расчётами на GPU уже давно - OpenCL. По производительности вычислений float карты NVidia всегда опережают AMD с аналогичным количеством и частотой потоковых процессоров. Процентов на 30-50. От использования double лучше по возможности уходить.

среда, 22 января 2020 г.

Использование буферов OpenGL в OpenCL - ошибка “InvalidContext”

#c_sharp #opengl #opencl


Мне требуется использовать буферы OpenGL в OpenCL.
при использовании метода clCreateFromGLBuffer выдаёт ошибку InvalidContext.
я где то прочитал что нужно добавить свойства при создании контекста OpenCl 

ContextProperty[] contextProperties = new[]
{
     new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, Win32.wglGetCurrentContext()),
     new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,Win32.GetDC(Process.GetCurrentProcess().MainWindowHandle)),
     new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle), 
}


я добавил но появилась ошибка при создании контекста


  System.AccessViolationException: Попытка чтения или записи в защищенную память.
Это часто свидетельствует о том, что другая память повреждена.


Также, констант CL_GL_CONTEXT_KHR и CL_WGL_HDC_KHR не было в библиотеке которую я
скачал в NuGet значения констант я нашёл на на этом сайте

Как это исправить?

полный код

Glfw.Init();
window = Glfw.CreateWindow(500, 500, "");
Glfw.MakeContextCurrent(window);
OpenGL gl = new OpenGL();

Platform[] platforms = Cl.GetPlatformIDs(out errorCode);
foreach (Platform platform in platforms)
{
     Device[] devices = Cl.GetDeviceIDs(platform, DeviceType.Gpu, out errorCode);

     if (devices.Length == 0)
     {
          continue;
     }

     _platform = platform;
     _device = devices[0];
     break;
}
ContextProperty[] contextProperties = new[]
{
     new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, Win32.wglGetCurrentContext()),
            new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,Win32.GetDC(window.Ptr)),
            new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle), 

};
_context = Cl.CreateContext(contextProperties, 1, new Device[] {_device}, null, IntPtr.Zero,
out errorCode);

    


Ответы

Ответ 1



вообщем ему не хватало одного элемента в массиве. ContextProperty[] contextProperties = new[] { new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, wglGetCurrentContext()), new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,wglGetCurrentDC()), new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle), new ContextProperty(0,IntPtr.Zero), }; вот так всё работает.

четверг, 19 декабря 2019 г.

Написать свой генератор псевдослучайных чисел

#cpp #c #математика #случайные_числа #opencl


Необходимо написать свой генератор, т. к. нет возможности добавить библиотеку со
встроенным. Можете подсказать пожалуйста ссылку или формулу, по которой можно на C,
где будут случайных числа между минимумом и максимумом. Типа int и double.

P. S. Пишу под OpenCL. Никаких встроенных готовых библиотек с этим нет. Есть варианты,
но там сложнее немного. 
Был ли у кого опыт написания примитивного ГПСЧ без каких-либо встроенных функций?
    


Ответы

Ответ 1



Когда-то давно (до С++11) писал по второму тому Кнута для 32 и 64 бит - если поможет... class Random { public: typedef int RandomValue; Random& operator = (int seed) { X = seed; return *this; } Random(int seed = 1):X(seed){}; int operator()(int seed = 0) { const int MM = 2147483647; const int AA = 48271; const int QQ = 44488; const int RR = 3399; if (seed != 0) X = seed; X = AA*(X%QQ)-RR*(X/QQ); if (X < 0) X += MM; return X-1; } int operator()(int min, int max) { return (*this)()%(max-min) + min; } private: int X; }; class Random64 { typedef unsigned long long uint64; public: typedef uint64 RandomValue; Random64& operator = (uint64 seed) { X = seed; return *this; } Random64(uint64 seed = 0):X(seed){}; uint64 operator()(uint64 seed = uint64(-1)) { const uint64 a = 3202034522624059733ULL; const uint64 c = 1ULL; if (seed != uint64(-1)) X = seed; uint64 Y = a * X + c; X = a * Y + c; Y = (Y&0xFFFFFFFF00000000ULL) | (X >> 32); return Y; } uint64 operator()(uint64 min, uint64 max) { return (*this)()%(max-min) + min; } private: uint64 X; };

Ответ 2



Кому нужно будет, вот решение : main { uint32_t stat[1]; stat[0] = 2595719; uint32_t rang = 0; int min = 10; int max = 1000; for (int i = 0; i < 10000; i++) { rang = rand(stat) % (max - min) + min; cout << "Random Number is " << rang << endl; } } uint32_t rand(uint32_t state[1]) { uint32_t x = state[0]; x ^= x << 13; x ^= x >> 17; x ^= x << 5; state[0] = x; return x; } Предложите, что подкорректировать, если есть варианты

Ответ 3



Для написания своего ГПСЧ можно использовать линейный конгруэнтный метод. Он довольно часто применяется в реализации стандартной библиотеки. Этот метод может сгенерировать статистически хорошую псевдослучайную последовательность (т. е. часта появления каждого числа будет примерно одинаковой), но этот метод не применим в криптографии, т. к. может быть легко взломан. Переносимую реализацию функции rand и srand можно найти в стандарте языка C (в качестве примера приведена реализация из стандарта C11): static unsigned long long int next = 1; int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } void srand(unsigned int seed) { next = seed; } ISO/IEC 9899:2011 Примечания Переменная next объявлена статической, т. к. предполагается, что она и (обе функции, к тому же) находится в файле stdlib.h.

Ответ 4



Почему бы вам не использовать стандартный метод для Си: srand(time(NULL)); digit = begin_num + rand() % n;

Ответ 5



Могу предложить еще один простой пример: class RandInt { using Cont = std::valarray; Cont v; static int k; public: RandInt(int min, int max, size_t seed) { k = seed; int langht = max - min; v = Cont(min, langht); for (int i = 1; i < langht; ++i) v[i] = v[i -1] + 1; } int operator ()() { v = v.cshift(k); ++k; return v[v.size()/2]; } }; int RandInt::k; int main(]) { RandInt r(-25, 25, 3); for (int i = 0; i < 20; ++i) std::cout << r() << '\n'; return 0; }

четверг, 5 декабря 2019 г.

Зачем на AMD GCN используется не нулевой NULL

#c #opencl


В описании этого коммита сказано:


  In amdgcn target, null pointers in global, constant, and generic address space
take value 0 but null pointers in private and local address space take value -1.


Зачем в AMD GCN так сделано?
    


Ответы

Ответ 1



Во-первых, значение нулевого указателя (null pointer value) по сути своей должно быть таковым, чтобы оно "указывало" на заведомо неиспользуемый адрес памяти. По-видимому в локальном адресном пространстве адрес 0x00000000 - вполне используемый адрес, т.е. подходящим внутренним представлением для null pointer он не является. Во-вторых, обратите внимание на аккуратное и грамотное использование терминологии автором прилинкованного текста. Речь идет о "null pointer" и "null pointer value", а не о NULL. NULL в тексте не упоминается вообще. Макро NULL - это null pointer constant. Его менять совершенно не нужно, да и нельзя. Он как был, так и остается именно нулевым, как того требует стандарт языка. Ненулевого NULL в языке С быть не может. Меняется только внутреннее представление null pointer value в локальном адресном пространстве. То есть меняется то значение, которое фактически получает указатель, которому присвоена null pointer constant. Неявная трансляция константного нуля в это внутреннее значение - задача компилятора. Другими словами, после данного изменения код вроде i32 addrspace(0)*p = 0; для указателя в локальном адресном пространстве будет тихонько транслироваться компилятором в занесение значения 0xFFFFFFFF в p. На уровне исходного кода исправлять нули на что-то другое не нужно.

Ответ 2



Необходимо понять, что NULL не имеет никакого отношения к нулевому адресу. NULL - это лишь универсальное определение невалидного указателя. Для того, чтобы понять, почему сделано именно так, нужно знать внутреннее устройство адресного пространства GCN. Просматривая whitepaper GCN, можно найти следующее заявление: In tandem with cache coherency, GCN introduces virtual memory through a combination of hardware and driver support. <...> More importantly, it paves the way for a single address space that is seamlessly shared by CPUs and GPUs. Следовательно, адресное пространство в GCN является общим для CPU и GPU и можно предположить, что нулевой адрес является валидным адресом для данной схемы. Если это так, то значение невалидного указателя не может быть нулевым, чтобы не совпадать с валидным адресом в памяти.

среда, 10 июля 2019 г.

Универсальные бинарники ядер для OpenCL

У меня есть 2 компьютера, в одном установлена Raden R9 290x, а в другом Raden R7 250, и далее речь пойдет только об видеокартах AMD. На обоих компьютерах установлены одни и те же драйвера. Я написал OpenCL ядро, скомпилировал его в бинарник и, в последствии, использую clCreateProgramWithBinary. Но я столкнулся с следующими сложностями:
Скомпилированные для этих двух устройств бинарники отличаются: для R7 бинарник весит ~500КБ, а для R9 ~1.5MB. При использовании бинарника на устройстве для которого он был скомпилирован не возникает никаких проблем, все происходит мгновенно, но если попытаться запустить бинарник для R7 на R9, то clBuildProgram исполняется очень долго(~1 мин.), а наоборот clBuildProgram - вообще вызывает access violation.
Мне необходимо получить бинарник, который будет работать на все видеокартах AMD, поддерживающих OpenCL. Как правильно скомпилировать OpenCL ядро, что бы оно корректно работало на всех устройствах?


Ответ

Есть частичное решение, обеспечивающее совместимость на уровне платформ и устройств - SPIR. В данный формат исходники можно скомпилировать например с помощью Intel OpenCL Code Builder. К сожалению результирующий файл все еще требует компиляции, но времени это занимает немного меньше чем для исходного кода.

пятница, 17 мая 2019 г.

Какую лучше архитектуру использовать для вычислений на GPU

Необходимо перенести вычисления с CPU на GPU. Начал гуглить про это всё, в итоге есть 2 похожие архитектуры - CUDA от Nvidia и OpenCL от AMD, второе можно и на Nvidia использовать. Вроде бы пишут, что видеокарты на AMD больше заточены под вычисления и быстрее на 30-40%.
У кого был опыт программирования на подобном. Можете прояснить пожалуйста, что лучше выбрать для себя?
Программу пишу на C#, но как понял, класс вычислений придется писать на C++ и подключать библиотеку к своей программе.


Ответ

Занимаюсь сложными гидродинамическими расчётами на GPU уже давно - OpenCL. По производительности вычислений float карты NVidia всегда опережают AMD с аналогичным количеством и частотой потоковых процессоров. Процентов на 30-50. От использования double лучше по возможности уходить.

воскресенье, 10 марта 2019 г.

Использование буферов OpenGL в OpenCL - ошибка “InvalidContext”

Мне требуется использовать буферы OpenGL в OpenCL. при использовании метода clCreateFromGLBuffer выдаёт ошибку InvalidContext. я где то прочитал что нужно добавить свойства при создании контекста OpenCl
ContextProperty[] contextProperties = new[] { new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, Win32.wglGetCurrentContext()), new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,Win32.GetDC(Process.GetCurrentProcess().MainWindowHandle)), new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle), }
я добавил но появилась ошибка при создании контекста
System.AccessViolationException: Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.
Также, констант CL_GL_CONTEXT_KHR и CL_WGL_HDC_KHR не было в библиотеке которую я скачал в NuGet значения констант я нашёл на на этом сайте
Как это исправить?
полный код
Glfw.Init(); window = Glfw.CreateWindow(500, 500, ""); Glfw.MakeContextCurrent(window); OpenGL gl = new OpenGL();
Platform[] platforms = Cl.GetPlatformIDs(out errorCode); foreach (Platform platform in platforms) { Device[] devices = Cl.GetDeviceIDs(platform, DeviceType.Gpu, out errorCode);
if (devices.Length == 0) { continue; }
_platform = platform; _device = devices[0]; break; } ContextProperty[] contextProperties = new[] { new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, Win32.wglGetCurrentContext()), new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,Win32.GetDC(window.Ptr)), new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle),
}; _context = Cl.CreateContext(contextProperties, 1, new Device[] {_device}, null, IntPtr.Zero, out errorCode);


Ответ

вообщем ему не хватало одного элемента в массиве.
ContextProperty[] contextProperties = new[] { new ContextProperty(ContextProperties.CL_GL_CONTEXT_KHR, wglGetCurrentContext()), new ContextProperty(ContextProperties.CL_WGL_HDC_KHR,wglGetCurrentDC()), new ContextProperty(ContextProperties.CL_CONTEXT_PLATFORM,_platform.handle), new ContextProperty(0,IntPtr.Zero),
};
вот так всё работает.