//+------------------------------------------------------------------+ //| opencl.mqh | //| Copyright 2021, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| Подключаем библиотеки | //+------------------------------------------------------------------+ #include //+------------------------------------------------------------------+ //| Class CMyOpenCL | //| Назначение: Класс организации работы с контекстом OpenCL | //+------------------------------------------------------------------+ class CMyOpenCL : public COpenCL { public: CMyOpenCL(void) {}; ~CMyOpenCL(void) {}; template int AddBufferFromArray(T &data[], const uint data_array_offset, const uint data_array_count, const uint flags); int AddBufferFromArray(matrix &data, const uint data_array_offset, const uint flags); bool CheckBuffer(const int index); //--- bool BufferFromMatrix(const int buffer_index, MATRIX &data, const uint data_array_offset, const uint flags); bool BufferRead(const int buffer_index, MATRIX &data, const uint cl_buffer_offset); bool BufferWrite(const int buffer_index, MATRIX &data, const uint cl_buffer_offset); }; //+------------------------------------------------------------------+ //| Метод создания буфера в контексте OpenCL | //+------------------------------------------------------------------+ template int CMyOpenCL::AddBufferFromArray(T &data[], const uint data_array_offset, const uint data_array_count, const uint flags) { //--- Поисе свободного элемента в динамическом массиве указателей int result = -1; for(int i = 0; i < m_buffers_total; i++) { if(m_buffers[i] != INVALID_HANDLE) continue; result = i; break; } //--- Если всободный элементне найден добавляем новый элемен в массив if(result < 0) { if(ArrayResize(m_buffers, m_buffers_total + 1) > 0) { m_buffers_total = ArraySize(m_buffers); result = m_buffers_total - 1; m_buffers[result] = INVALID_HANDLE; } else return result; } //--- Создаём буфер в контексте OpenCL if(!BufferFromArray(result, data, data_array_offset, data_array_count, flags)) return -1; //--- return result; } //+------------------------------------------------------------------+ //| Метод создания буфера в контексте OpenCL | //+------------------------------------------------------------------+ int CMyOpenCL::AddBufferFromArray(matrix &data, const uint data_array_offset, const uint flags) { //--- Поисе свободного элемента в динамическом массиве указателей int result = -1; for(int i = 0; i < m_buffers_total; i++) { if(m_buffers[i] != INVALID_HANDLE) continue; result = i; break; } //--- Если всободный элементне найден добавляем новый элемен в массив if(result < 0) { if(ArrayResize(m_buffers, m_buffers_total + 1) > 0) { m_buffers_total = ArraySize(m_buffers); result = m_buffers_total - 1; m_buffers[result] = INVALID_HANDLE; } else return result; } //--- Создаём буфер в контексте OpenCL if(!BufferFromMatrix(result, data, data_array_offset, flags)) return -1; return result; } //+------------------------------------------------------------------+ //| Метод проверки действительности указателя на буфер по индексу | //| в динамическом массиве | //+------------------------------------------------------------------+ bool CMyOpenCL::CheckBuffer(const int index) { if(index < 0 || index > m_buffers_total) return false; return m_buffers[index] != INVALID_HANDLE; } //+------------------------------------------------------------------+ //| BufferFromMatrix | //+------------------------------------------------------------------+ bool CMyOpenCL::BufferFromMatrix(const int buffer_index, MATRIX &data, const uint data_array_offset, const uint flags) { //--- check parameters if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE) return(false); if(buffer_index < 0 || buffer_index >= m_buffers_total) return(false); //--- buffer does not exists, create it if(m_buffers[buffer_index] == INVALID_HANDLE) { uint size_in_bytes = (typename(MATRIX)=="matrix" ? sizeof(double) : sizeof(float))*(int)(data.Rows()*data.Cols()); int buffer_handle = CLBufferCreate(m_context, size_in_bytes, flags); if(buffer_handle != INVALID_HANDLE) { m_buffers[buffer_index] = buffer_handle; } else return(false); } //--- write data to OpenCL buffer ResetLastError(); if(!CLBufferWrite(m_buffers[buffer_index], data_array_offset, data)) { PrintFormat("Write to buffer error %d", GetLastError()); return(false); } //--- return(true); } //+------------------------------------------------------------------+ //| BufferRead | //+------------------------------------------------------------------+ bool CMyOpenCL::BufferRead(const int buffer_index, MATRIX &data, const uint cl_buffer_offset) { //--- check parameters if(buffer_index < 0 || buffer_index >= m_buffers_total || data.Rows() <= 0) return(false); if(m_buffers[buffer_index] == INVALID_HANDLE) return(false); if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE) return(false); //--- read data from OpenCL buffer if(!CLBufferRead(m_buffers[buffer_index], cl_buffer_offset, data)) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| BufferWrite | //+------------------------------------------------------------------+ bool CMyOpenCL::BufferWrite(const int buffer_index, MATRIX &data, const uint cl_buffer_offset) { //--- check parameters if(buffer_index < 0 || buffer_index >= m_buffers_total || data.Rows() <= 0) return(false); if(m_buffers[buffer_index] == INVALID_HANDLE) return(false); if(m_context == INVALID_HANDLE || m_program == INVALID_HANDLE) return(false); //--- write data to OpenCL buffer if(!CLBufferWrite(m_buffers[buffer_index], cl_buffer_offset, data)) return(false); //--- return(true); } //+------------------------------------------------------------------+