- Статьи по разработке торговых приложений
- Работа с SQL-базами данных
- Расчет маржи: Retail Forex, Futures - Для продвинутых пользователей - Торговые операции
__kernel void Func( int n, __global float *x, __global float *w, __global float *out) { ... }
Точно так же, как out
то есть вот этот код полностью правилен?
const string cl_src= "__kernel void Func( int n, \r\n" " __global float *x, \r\n" " __global float *w, \r\n" " __global float *out) \r\n" "{ \r\n" " int n = get_global_id( 0 ); \r\n" " float x = get_global_id( 1 ); \r\n" " float w = get_global_id( 2 ); \r\n" " for( int i = 0; i < n; i ++ ) \r\n" " { \r\n" " out = out+x[i]*w[i]; \r\n" " } \r\n" "} \r\n";
то есть вот этот код полностью правилен?
Нет. Вот это лишнее:
" float x = get_global_id( 1 ); \r\n" " float w = get_global_id( 2 ); \r\n"
Кроме того, если out у вас не массив (пардон, не обратил внимания сразу), то придётся избавляться от одновременного доступа при помощи атомарных функций. Но в этом случае придётся уходить от float, так как атомарные функции работают только с целочисленными типами (по крайней мере, в OpenCl 1.2 было так).
Сейчас занят, не могу написать код, может ближе к вечеру (если вам не предложат решение или сами не разберетесь).
P.S. Посмотрите мою статью про поиск паттернов, может помочь понять, как всё это работает
P.P.S. И цикл там не нужен
Выложите код на mql, как оно должно работать, и я вам напишу его на OpenCl
- www.mql5.com
Вот решение.
1) Код OpenCL (файл test_001.cl)
#pragma OPENCL EXTENSION cl_khr_fp64 : enable #pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable #pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable #pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable #pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable #pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable #pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable __kernel void Func( int n, double k, __global double *x, __global double *w, __global int *out) { size_t i = get_global_id(0); int a = x[i]*w[i]*k; atomic_add(out,a); }
2) Скрипт для запуска
#property version "1.00" //--- исходные коды кернелов #resource "test_001.cl" as string cl_test //--- COpenCL class #include <OpenCL/OpenCL.mqh> #define BUF_LEN 10 double buf1[BUF_LEN]= { 0.123, 1.234, 2.345, 3.456, 4.567, 5.678, 6.789, 7.891, 8.912, 9.123}; double buf2[BUF_LEN]= {10.123,11.234,12.345,13.456,14.567,15.678,16.789,17.891,18.912,19.123}; COpenCL *ocl; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { Print(" -=< Start >=-"); //--- double sum=0; for(int i=0; i<BUF_LEN; i++) sum+= buf1[i]*buf2[i]; Print("sum = ",sum); //--- double k = 100000; //точность до 5-го знака после точки //--- инициализация OpenCl if(Init()==false) return; // создаём буферы int result[1]; ocl.BufferFromArray(0,buf1, 0,BUF_LEN,CL_MEM_READ_ONLY); ocl.BufferFromArray(1,buf2, 0,BUF_LEN,CL_MEM_READ_ONLY); ocl.BufferFromArray(2,result,0,BUF_LEN,CL_MEM_READ_WRITE); // задаём аргументы int n = BUF_LEN; ocl.SetArgument(0, 0, n); ocl.SetArgument(0, 1, k); ocl.SetArgumentBuffer(0, 2, 0); // x ocl.SetArgumentBuffer(0, 3, 1); // w ocl.SetArgumentBuffer(0, 4, 2); // out //--- пространство задач кернела одномерное //--- и количество задач в первом (и единственном) измерении равно размеру буфера uint global_size[1]= {BUF_LEN}; //--- начальное смещение в пространстве задач равно нулю uint work_offset[1]= {0}; //--- запускаем выполнение кернела ocl.Execute(0,1,work_offset,global_size); //--- читаем результат ocl.BufferRead(2,result,0,0,1); Print("sum = ",double(result[0])/k); //--- деинициализация OpenCl Deinit(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Init(void) { //--- создание объекта класса COpenCL ocl=new COpenCL; while(!IsStopped()) { //--- инициализация OpenCL ::ResetLastError(); if(!ocl.Initialize(cl_test,true)) { Print("Ошибка инициализации OpenCL"); break; } //--- проверка поддержки работы с double if(!ocl.SupportDouble()) { Print("Работа с double (cl_khr_fp64) не поддерживается устройством"); break; } //--- установка количества кернелов if(!ocl.SetKernelsCount(1)) break; //--- создание кернелов ocl.KernelCreate(0,"Func"); //--- создание буферов if(!ocl.SetBuffersCount(3)) { Print("Ошибка создания буферов"); break; } return true; } Deinit(); return false; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void Deinit() { if(ocl!=NULL) { //--- remove OpenCL objects ocl.Shutdown(); delete ocl; ocl=NULL; } } //+------------------------------------------------------------------+
Сравнение результатов:
Вообще-то, всё наоборот.
Блин, это круто, спасибо большое за столь подробный ответ, мне надо немного времени чтобы переварить ваш код, я напишу вам лично, если будут вопросы. Я новичок в OpenCL, все пытаюсь его освоить, но со скрипом большим :-(
ТО что вы написали - правда круто.
Еще раз огромное спасибо.
- www.mql5.com
для маленьких задач GPU не подходит, нужно действительно что то сложное и долго считаемое
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования