309 lines
9.3 KiB
MQL5
309 lines
9.3 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Main.mqh |
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
#property link "https://www.mql5.com"
|
|
#property strict
|
|
|
|
#ifndef SCALERBYLEO_SRC_CL_MAIN_MQH
|
|
#define SCALERBYLEO_SRC_CL_MAIN_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
//-- incluimos hashmap
|
|
#include <TSN\\GCol\\HashMap.mqh>
|
|
#include <TSN\\GCol\\GenericHashes.mqh>
|
|
|
|
//-- tambien los kerneles
|
|
#include "..\\Kernels\\Rsrc.mqh"
|
|
#include "..\\..\\..\\CLByLeo\\SharedCtx.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| Defines |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef SCALERBYLEO_CL_DEVICE
|
|
#define SCALERBYLEO_CL_DEVICE (CL_USE_ANY)
|
|
#endif // SCALERBYLEO_CL_DEVICE
|
|
|
|
//---
|
|
enum ENUM_CLCONTEXT_MANAGER_LAST_ERR
|
|
{
|
|
CLCONTEXT_MANAGER_LAST_ERR_NOT,
|
|
CLCONTEXT_MANAGER_LAST_ERR_INVALID_HANDLE,
|
|
CLCONTEXT_MANAGER_LAST_ERR_CL,
|
|
};
|
|
|
|
//---
|
|
#define SCALERBYLEO_CLCTX_IS_CREATE (CCLCtxShared::s_context != INVALID_HANDLE && s_program != INVALID_HANDLE)
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
class COpenCLCtxManager
|
|
{
|
|
private:
|
|
static CHashMapFastP(int, uint, _fibbo) s_hash;
|
|
static CHashMapFast(string, int) s_hash_kernel;
|
|
|
|
//---
|
|
template<typename TValue>
|
|
static bool UpdateVectorDataInternal(int &handle, vector<TValue> &vec, uint flags);
|
|
|
|
|
|
public:
|
|
COpenCLCtxManager(void) {}
|
|
~COpenCLCtxManager(void) {}
|
|
|
|
//---
|
|
static string s_last_build_log;
|
|
static int s_program;
|
|
static ENUM_CLCONTEXT_MANAGER_LAST_ERR s_last_err;
|
|
|
|
|
|
//---
|
|
static bool ProgramInit(const string& src);
|
|
static bool KernelGet(const string& name, int& h);
|
|
|
|
//---
|
|
static bool UpdateVectorData(int& h, vector& vec, uint flags);
|
|
|
|
//---
|
|
static void Deinit(const int reason);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
int COpenCLCtxManager::s_program = INVALID_HANDLE;
|
|
template<typename TFlt>
|
|
string COpenCLCtxManager::s_last_build_log = "";
|
|
template<typename TFlt>
|
|
ENUM_CLCONTEXT_MANAGER_LAST_ERR COpenCLCtxManager::s_last_err = CLCONTEXT_MANAGER_LAST_ERR_NOT;
|
|
|
|
//---
|
|
template<typename TFlt>
|
|
CHashMapFastP(int, uint, _fibbo) COpenCLCtxManager::s_hash;
|
|
template<typename TFlt>
|
|
CHashMapFast(string, int) COpenCLCtxManager::s_hash_kernel;
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
static bool COpenCLCtxManager::ProgramInit(const string& src)
|
|
{
|
|
//---
|
|
if(SCALERBYLEO_CLCTX_IS_CREATE)
|
|
return true;
|
|
|
|
//---
|
|
::ResetLastError();
|
|
|
|
//---
|
|
if(!CCLCtxShared::ContextInit())
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
if((s_program = CLProgramCreate(CCLCtxShared::s_context, src, s_last_build_log)) == INVALID_HANDLE)
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
// En caso hayamos fallado en su creacion igual lo liberamos (dado que si logramos iniciar)
|
|
CCLCtxShared::ContextFree();
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
static void COpenCLCtxManager::Deinit(const int reason)
|
|
{
|
|
//---
|
|
// Si en caso la razon de remove fue chart change o parameotrs
|
|
// Los objetod golbales como tal se conservan no se liberan.. por lo que ya no se volvera a llamar a esa funcion o limpiar lo que tiene
|
|
// asi que lo prevenimos.
|
|
//---
|
|
if(reason == REASON_CHARTCHANGE || reason == REASON_PARAMETERS)
|
|
{
|
|
//FastLog(FUNCION_ACTUAL, WARNING_TEXT, "No se limpara el factory de features dado que la razon de deinit es chart-change,params");
|
|
return;
|
|
}
|
|
|
|
//---
|
|
if(s_program != INVALID_HANDLE)
|
|
{
|
|
CLProgramFree(s_program);
|
|
s_program = INVALID_HANDLE;
|
|
CCLCtxShared::ContextFree();
|
|
}
|
|
|
|
//---
|
|
CHashMapFastIteratorP(int, uint, _fibbo) it = s_hash.BeginIteration();
|
|
while(it.IsValid())
|
|
{
|
|
CLBufferFree(it.Key());
|
|
it.Next();
|
|
}
|
|
s_hash.Clear();
|
|
|
|
//---
|
|
CHashMapFastIterator(string, int) it_kernels = s_hash_kernel.BeginIteration();
|
|
while(it_kernels.IsValid())
|
|
{
|
|
CLKernelFree(it_kernels.Val());
|
|
it_kernels.Next();
|
|
}
|
|
s_hash_kernel.Clear();
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
static bool COpenCLCtxManager::KernelGet(const string &name, int& h)
|
|
{
|
|
//---
|
|
if(!s_hash_kernel.ReserveSlot(name))
|
|
{
|
|
const uint p = s_hash_kernel.m_last_pos_tbl;
|
|
h = s_hash_kernel.m_table[p].value;
|
|
return true;
|
|
}
|
|
|
|
//---
|
|
if((h = CLKernelCreate(s_program, name)) == INVALID_HANDLE)
|
|
{
|
|
//---
|
|
const uint p = s_hash_kernel.m_last_pos_tbl;
|
|
s_hash_kernel.m_bit_pos = int(TSN_FASTHASHMAP_INDEX_GET_BITPOS_WCORR(p)); // truqueamos
|
|
s_hash_kernel.RemoveLastFindCall();
|
|
|
|
//---
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
const uint p = s_hash_kernel.m_last_pos_tbl;
|
|
s_hash_kernel.m_table[p].value = h; // ya poenmos
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// La idea siempre revismos un vec
|
|
// dependie del TFlt tenemos que evitanso una copia o hacer la copia\conversion..
|
|
// Si en caso tflt es dbl entonces sin copias..
|
|
template<typename TFlt>
|
|
static bool COpenCLCtxManager::UpdateVectorData(int &h, vector &vec, uint flags)
|
|
{
|
|
//---
|
|
// 1. si es float enveonces el vector (De datos) hay que converitlo a float (dado qeu es dbl)
|
|
// 2. si en cambio la clase es dbl (Es pro que el usuario precisa tener soporte para dbl) lo mandamos tal cual
|
|
|
|
//---
|
|
if(sizeof(TFlt) == sizeof(float))
|
|
{
|
|
vectorf f;
|
|
f.Assign(vec);
|
|
return UpdateVectorDataInternal(h, f, flags);
|
|
}
|
|
else
|
|
return UpdateVectorDataInternal(h, vec, flags);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template<typename TFlt>
|
|
template<typename TValue>
|
|
static bool COpenCLCtxManager::UpdateVectorDataInternal(int &handle, vector<TValue> &vec, uint flags)
|
|
{
|
|
//---
|
|
const uint vec_size = uint(vec.Size());
|
|
const uint vec_bytes = uint(vec_size * sizeof(TValue));
|
|
|
|
//---
|
|
// en caso haya cambiado de tamaño entonces tambine cremos
|
|
::ResetLastError();
|
|
if(handle == INVALID_HANDLE)
|
|
{
|
|
if((handle = CLBufferCreate(CCLCtxShared::s_context, vec_bytes, flags)) == INVALID_HANDLE)
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
return false;
|
|
}
|
|
s_hash.Add(handle, vec_bytes);
|
|
}
|
|
else
|
|
{
|
|
uint bytes;
|
|
if(!s_hash.TryGet(handle, bytes))
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_INVALID_HANDLE;
|
|
return false;
|
|
}
|
|
if(bytes != vec_bytes)
|
|
{
|
|
//---
|
|
CLBufferFree(handle);
|
|
|
|
//---
|
|
if((handle = CLBufferCreate(CCLCtxShared::s_context, vec_bytes, flags)) == INVALID_HANDLE)
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
return false;
|
|
}
|
|
|
|
//--- actulizamos el tamaño
|
|
const uint p = s_hash.m_last_pos_tbl;
|
|
s_hash.m_table[p].value = vec_bytes;
|
|
}
|
|
// iguales no actulizamos
|
|
}
|
|
|
|
//--- actulizamos
|
|
if(!CLBufferWrite(handle, 0, vec))
|
|
{
|
|
s_last_err = CLCONTEXT_MANAGER_LAST_ERR_CL;
|
|
return false;
|
|
}
|
|
|
|
//---
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Macros de ayuda |
|
|
//+------------------------------------------------------------------+
|
|
#define OPENCLMANAGER_MAKE_VECTOR(h, vec, flags) if(!COpenCLCtxManager<TFlt>::UpdateVectorData(h, vec, flags)) { m_last_err=SCALERBYLEO_ERR_IN_CTX_MANAGER_CL; return false; }
|
|
|
|
|
|
|
|
//--- end namepsace
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
#endif // SCALERBYLEO_SRC_CL_MAIN_MQH
|