forked from rinkugohil30897/NeuroBook
486 lines
37 KiB
MQL5
486 lines
37 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| BufferDouble.mqh |
| |
//| Copyright 2021, MetaQuotes Ltd. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2021, MetaQuotes Ltd."
| |
#property link "https://www.mql5.com"
| |
//+------------------------------------------------------------------+
| |
//| Connect libraries |
| |
//+------------------------------------------------------------------+
| |
#include <Arrays\Array.mqh>
| |
#include "opencl.mqh"
| |
//+------------------------------------------------------------------+
| |
//| Class CBufferType |
| |
//| Purpose: Dynamic data buffer class |
| |
//+------------------------------------------------------------------+
| |
class CBufferType: public CObject
| |
{
| |
protected:
| |
CMyOpenCL* m_cOpenCL; // OpenCL context object
| |
int m_myIndex; // data buffer index in context
| |
public:
| |
CBufferType(void);
| |
~CBufferType(void);
| |
//---
| |
MATRIX m_mMatrix;
| |
//--- method for initializing the buffer with initial values
| |
virtual bool BufferInit(const ulong rows, const ulong columns, const TYPE value = 0);
| |
//--- create a new buffer in the OpenCL context
| |
virtual bool BufferCreate(CMyOpenCL *opencl);
| |
//--- delete a buffer in the OpenCL context
| |
virtual bool BufferFree(void);
| |
//--- read data of the buffer from the OpenCL context
| |
virtual bool BufferRead(void);
| |
//--- write buffer data to the OpenCL context
| |
virtual bool BufferWrite(void);
| |
//--- get buffer index
| |
virtual int GetIndex(void);
| |
//--- change buffer index
| |
virtual bool SetIndex(int index)
| |
{
| |
if(!m_cOpenCL.BufferFree(m_myIndex))
| |
return false;
| |
m_myIndex = index;
| |
return true;
| |
}
| |
//--- copy buffer data to the array
| |
virtual int GetData(TYPE &values[], bool load = true);
| |
virtual int GetData(MATRIX &values, bool load = true);
| |
virtual int GetData(CBufferType *values, bool load = true);
| |
//--- calculate the average value of the data buffer
| |
virtual TYPE MathMean(void);
| |
//--- vector operations
| |
virtual bool SumArray(CBufferType *src);
| |
virtual int Scaling(TYPE value);
| |
virtual bool Split(CBufferType* target1, CBufferType* target2, const int position);
| |
virtual bool Concatenate(CBufferType* target1, CBufferType* target2, const ulong positions1, const ulong positions2);
| |
//--- file handling methods
| |
virtual bool Save(const int file_handle);
| |
virtual bool Load(const int file_handle);
| |
//--- class identifier
| |
virtual int Type(void) const { return defBuffer; }
| |
| |
ulong Rows(void) const { return m_mMatrix.Rows(); }
| |
ulong Cols(void) const { return m_mMatrix.Cols(); }
| |
ulong Total(void) const { return (m_mMatrix.Rows() * m_mMatrix.Cols()); }
| |
TYPE At(uint index) const { return m_mMatrix.Flat(index); }
| |
TYPE operator[](ulong index) const { return m_mMatrix.Flat(index); }
| |
VECTOR Row(ulong row) { return m_mMatrix.Row(row); }
| |
VECTOR Col(ulong col) { return m_mMatrix.Col(col); }
| |
bool Row(VECTOR& vec, ulong row) { return m_mMatrix.Row(vec, row); }
| |
bool Col(VECTOR& vec, ulong col) { return m_mMatrix.Col(vec, col); }
| |
bool Activation(MATRIX& mat_out, ENUM_ACTIVATION_FUNCTION func) { return m_mMatrix.Activation(mat_out, func);}
| |
bool Derivative(MATRIX& mat_out, ENUM_ACTIVATION_FUNCTION func) { return m_mMatrix.Derivative(mat_out, func);}
| |
bool Reshape(ulong rows, ulong cols){ return m_mMatrix.Reshape(rows, cols); }
| |
| |
bool Update(uint index, TYPE value)
| |
{
| |
if(index >= Total())
| |
return false;
| |
m_mMatrix.Flat(index, value);
| |
return true;
| |
}
| |
| |
bool Update(uint row, uint col, TYPE value)
| |
{
| |
if(row >= Rows() || col >= Cols())
| |
return false;
| |
m_mMatrix[row, col] = value;
| |
return true;
| |
}
| |
};
| |
//+------------------------------------------------------------------+
| |
//| Class constructor |
| |
//+------------------------------------------------------------------+
| |
CBufferType::CBufferType(void) : m_myIndex(-1)
| |
{
| |
m_cOpenCL = NULL;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Class destructor |
| |
//+------------------------------------------------------------------+
| |
CBufferType::~CBufferType(void)
| |
{
| |
if(m_cOpenCL && m_myIndex >= 0)
| |
{
| |
if(m_cOpenCL.BufferFree(m_myIndex))
| |
{
| |
m_myIndex = -1;
| |
m_cOpenCL = NULL;
| |
}
| |
}
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Creating a new buffer in the OpenCL context |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::BufferCreate(CMyOpenCL *opencl)
| |
{
| |
//--- source data checking bock
| |
if(!opencl)
| |
{
| |
BufferFree();
| |
return false;
| |
}
| |
//--- if the received pointer matches the previously saved one, copy the buffer contents to the context memory
| |
if(opencl == m_cOpenCL && m_myIndex >= 0)
| |
return BufferWrite();
| |
| |
//--- check the presence of a previously saved pointer to OpenCL context
| |
//--- if present, delete the buffer from the unused context
| |
if(m_cOpenCL && m_myIndex >= 0)
| |
{
| |
if(m_cOpenCL.BufferFree(m_myIndex))
| |
{
| |
m_myIndex = -1;
| |
m_cOpenCL = NULL;
| |
}
| |
else
| |
return false;
| |
}
| |
//--- create a new buffer in the specified OpenCL context
| |
if((m_myIndex = opencl.AddBufferFromArray(m_mMatrix, 0, CL_MEM_READ_WRITE)) < 0)
| |
return false;
| |
m_cOpenCL = opencl;
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for removing the buffer from the OpenCL context |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::BufferFree(void)
| |
{
| |
//--- check the presence of a previously saved pointer to OpenCL context
| |
//--- if present, delete the buffer from the unused context
| |
if(m_cOpenCL && m_myIndex >= 0)
| |
if(m_cOpenCL.BufferFree(m_myIndex))
| |
{
| |
m_myIndex = -1;
| |
m_cOpenCL = NULL;
| |
return true;
| |
}
| |
if(m_myIndex >= 0)
| |
m_myIndex = -1;
| |
//---
| |
return false;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for reading data from the buffer in the OpenCL context |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::BufferRead(void)
| |
{
| |
if(!m_cOpenCL || m_myIndex < 0)
| |
return false;
| |
//---
| |
return m_cOpenCL.BufferRead(m_myIndex, m_mMatrix, 0);
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for writing data to the buffer in the OpenCL context |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::BufferWrite(void)
| |
{
| |
if(!m_cOpenCL || m_myIndex < 0)
| |
return false;
| |
//---
| |
return m_cOpenCL.BufferWrite(m_myIndex, m_mMatrix, 0);
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for initializing the buffer with initial values |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::BufferInit(ulong rows, ulong columns, TYPE value)
| |
{
| |
if(rows <= 0 || columns <= 0)
| |
return false;
| |
//---
| |
m_mMatrix = MATRIX::Full(rows, columns, value);
| |
if(m_cOpenCL)
| |
{
| |
CMyOpenCL *opencl=m_cOpenCL;
| |
BufferFree();
| |
return BufferCreate(opencl);
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for getting buffer values |
| |
//+------------------------------------------------------------------+
| |
int CBufferType::GetData(TYPE &values[], bool load = true)
| |
{
| |
if(load && !BufferRead())
| |
return -1;
| |
if(ArraySize(values) != Total() &&
| |
ArrayResize(values, (uint)Total()) <= 0)
| |
return false;
| |
//---
| |
for(uint i = 0; i < Total(); i++)
| |
values[i] = m_mMatrix.Flat(i);
| |
return (int)Total();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for getting buffer values |
| |
//+------------------------------------------------------------------+
| |
int CBufferType::GetData(MATRIX &values, bool load = true)
| |
{
| |
if(load && !BufferRead())
| |
return -1;
| |
//---
| |
values = m_mMatrix;
| |
return (int)Total();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for getting buffer values |
| |
//+------------------------------------------------------------------+
| |
int CBufferType::GetData(CBufferType *values, bool load = true)
| |
{
| |
if(!values)
| |
return -1;
| |
if(load && !BufferRead())
| |
return -1;
| |
values.m_mMatrix.Copy(m_mMatrix);
| |
return (int)values.Total();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for summing up elements of two data buffers |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::SumArray(CBufferType *src)
| |
{
| |
//--- check source data array
| |
if(!src || src.Total() != Total())
| |
return(false);
| |
//---
| |
if(!m_cOpenCL)
| |
{
| |
//--- resizing the matrix
| |
MATRIX temp = src.m_mMatrix;
| |
if(!temp.Reshape(Rows(), Cols()))
| |
return(false);
| |
//--- adding matrices
| |
m_mMatrix += temp;
| |
}
| |
else
| |
{
| |
if(src.GetIndex() < 0 && !BufferCreate(m_cOpenCL))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_inputs1, m_myIndex))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_inputs2, src.GetIndex()))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Sum, def_sum_outputs, m_myIndex))
| |
return false;
| |
uint off_set[] = {0};
| |
uint NDRange[] = {(uint)Total()};
| |
if(!m_cOpenCL.Execute(def_k_Sum, 1, off_set, NDRange))
| |
return false;
| |
}
| |
//---
| |
return(true);
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Method for computing the average value of the array |
| |
//+------------------------------------------------------------------+
| |
TYPE CBufferType::MathMean(void)
| |
{
| |
return m_mMatrix.Mean();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Get the index of the buffer in the OpenCL context |
| |
//+------------------------------------------------------------------+
| |
int CBufferType::GetIndex(void)
| |
{
| |
if(!m_cOpenCL || m_myIndex < 0)
| |
{
| |
m_myIndex = -1;
| |
m_cOpenCL = NULL;
| |
return m_myIndex;
| |
}
| |
//---
| |
if(!m_cOpenCL.CheckBuffer(m_myIndex))
| |
m_myIndex = BufferCreate(m_cOpenCL);
| |
//---
| |
return m_myIndex;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| Data scaling method (multiplying by a constant) |
| |
//+------------------------------------------------------------------+
| |
int CBufferType::Scaling(TYPE value)
| |
{
| |
if(!m_cOpenCL)
| |
m_mMatrix *= value;
| |
else
| |
{
| |
if(m_myIndex <= 0)
| |
return false;
| |
//--- pass parameters to the kernel
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_LineActivation, def_activ_inputs, m_myIndex))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_LineActivation, def_activ_outputs, m_myIndex))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_LineActivation, def_activ_param_a, value))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_LineActivation, def_activ_param_b, 0))
| |
return false;
| |
//--- place kernel to the execution queue
| |
int off_set[] = {0};
| |
int NDRange[] = { (int)Total() };
| |
if(!m_cOpenCL.Execute(def_k_LineActivation, 1, off_set, NDRange))
| |
return false;
| |
}
| |
//---
| |
return (int)Total();
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::Save(const int file_handle)
| |
{
| |
if(file_handle == INVALID_HANDLE)
| |
return false;
| |
if(m_myIndex >= 0)
| |
if(!BufferRead())
| |
return false;
| |
//---
| |
if(FileWriteInteger(file_handle, Type()) < INT_VALUE)
| |
return false;
| |
if(FileWriteLong(file_handle, Rows()) < sizeof(long))
| |
return false;
| |
if(FileWriteLong(file_handle, Cols()) < sizeof(long))
| |
return false;
| |
//---
| |
for(ulong r = 0; r < Rows(); r++)
| |
for(ulong c = 0; c < Cols(); c++)
| |
if(FileWriteDouble(file_handle, m_mMatrix[r, c]) < sizeof(double))
| |
return false;
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::Load(const int file_handle)
| |
{
| |
if(file_handle == INVALID_HANDLE)
| |
return false;
| |
if(FileReadInteger(file_handle) != Type())
| |
return false;
| |
//---
| |
ulong rows = FileReadLong(file_handle);
| |
ulong cols = FileReadLong(file_handle);
| |
if(!m_mMatrix.Init(rows, cols))
| |
return false;
| |
for(ulong r = 0; r < rows; r++)
| |
for(ulong c = 0; c < cols; c++)
| |
m_mMatrix[r, c] = (TYPE)FileReadDouble(file_handle);
| |
//---
| |
if(m_myIndex >= 0)
| |
{
| |
if(!BufferFree())
| |
return false;
| |
if(!BufferCreate(m_cOpenCL))
| |
return false;
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::Split(CBufferType *target1, CBufferType *target2, const int position)
| |
{
| |
if(!target1 || !target2)
| |
return false;
| |
//---
| |
if(!m_cOpenCL)
| |
{
| |
ulong split[] = {position};
| |
MATRIX m[];
| |
if(!m_mMatrix.Vsplit(split, m))
| |
return false;
| |
if(target1!=GetPointer(this))
| |
target1.m_mMatrix = m[0];
| |
target2.m_mMatrix = m[1];
| |
}
| |
else
| |
{
| |
if((int)target1.Total() < position)
| |
return false;
| |
if(target1.GetIndex() < 0 && !target1.BufferCreate(m_cOpenCL))
| |
return false;
| |
if(target2.GetIndex() < 0 && !target2.BufferCreate(m_cOpenCL))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_source, m_myIndex))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_target1, target1.GetIndex()))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Split, def_split_target2, target2.GetIndex()))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_source, (int)Total()))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_target1, position))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Split, def_split_total_target2, (int)target2.Total()))
| |
return false;
| |
//--- place kernel to the execution queue
| |
int off_set[] = {0};
| |
int NDRange[] = {(int)Total()};
| |
ResetLastError();
| |
if(!m_cOpenCL.Execute(def_k_Split, 1, off_set, NDRange))
| |
return false;
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
| |
//| |
| |
//+------------------------------------------------------------------+
| |
bool CBufferType::Concatenate(CBufferType *source1, CBufferType *source2, const ulong positions1, const ulong positions2)
| |
{
| |
if(!source1 || source1.Total() < positions1)
| |
return false;
| |
if(!source2 || source2.Total() < positions2)
| |
return false;
| |
//---
| |
if(!m_cOpenCL)
| |
{
| |
m_mMatrix = source1.m_mMatrix;
| |
if(!m_mMatrix.Resize(m_mMatrix.Rows(), positions1 + positions2))
| |
return false;
| |
for(ulong c = 0; c < positions2; c++)
| |
if(!m_mMatrix.Col(source2.m_mMatrix.Col(c), positions1 + c))
| |
return false;
| |
}
| |
else
| |
{
| |
if(source1.Total() < positions1)
| |
return false;
| |
if(source2.Total() < positions2)
| |
return false;
| |
if(Total() < positions1 + positions2)
| |
return false;
| |
if(source1.GetIndex() < 0 && !source1.BufferCreate(m_cOpenCL))
| |
return false;
| |
if(source2.GetIndex() < 0 && !source2.BufferCreate(m_cOpenCL))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_source1, source1.GetIndex()))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_source2, source2.GetIndex()))
| |
return false;
| |
if(!m_cOpenCL.SetArgumentBuffer(def_k_Concatenate, def_concat_target, m_myIndex))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_target, (int)Total()))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_source1, (int)positions1))
| |
return false;
| |
if(!m_cOpenCL.SetArgument(def_k_Concatenate, def_concat_total_sourse2, (int)positions2))
| |
return false;
| |
//--- place kernel to the execution queue
| |
int off_set[] = {0};
| |
int NDRange[] = {(int)Total()};
| |
ResetLastError();
| |
if(!m_cOpenCL.Execute(def_k_Concatenate, 1, off_set, NDRange))
| |
return false;
| |
}
| |
//---
| |
return true;
| |
}
| |
//+------------------------------------------------------------------+
|