Warrior_EA/DirectML/WarriorCPU.h
AnimateDread 6a687cda41 feat: add SGD+momentum optimizer and input-driven hyperparameters
Replace hardcoded lr and momentum with new input variables for Adam and
SGD+momentum. Add OpenCL kernel LSTM_UpdateWeightsMomentum alongside the
existing Adam kernel. Update comments and revert beta1 to book default 0.9.
2026-07-18 14:56:41 -04:00

106 lines
6.5 KiB
C++

//+------------------------------------------------------------------+
//| Warrior_EA |
//| Multithreaded CPU compute fallback - used when neither |
//| OpenCL nor the D3D12/DirectML tier are available (e.g. |
//| a VM with no GPU passthrough). Same buffer-handle model |
//| as WarriorDML.dll but full double precision throughout |
//| (no GPU float roundtrip) and work is spread across a |
//| configurable pool of worker threads instead of a device. |
//+------------------------------------------------------------------+
// Flat C ABI so MQL5 can #import this DLL directly. Function names and
// argument order/semantics mirror WarriorDML.h / AI\Network.cl 1:1 so the
// two backends are interchangeable behind CDirectMLMy in AI\Network.mqh.
#pragma once
#define WARRIORCPU_API extern "C" __declspec(dllexport)
// Every exported function (besides CPU_Init/CPU_GetHardwareConcurrency) takes a
// CpuHandle as its first argument - an opaque pointer to a heap-allocated,
// self-contained context (its own thread pool, buffer table and mutex) that
// CPU_Init() allocates and the caller (CDirectMLMy on the MQL5 side) is
// responsible for remembering and passing back on every subsequent call, then
// releasing via CPU_Shutdown(). No state is shared between contexts and this
// DLL keeps no global/static mutable state of its own, so it can be loaded any
// number of times and driven by any number of instances/threads in parallel -
// a fault or a wedged call against one context can never poison another
// context's calls, unlike a process-wide singleton would.
// A plain `long long` (not C++ `long`, which is only 32 bits on Windows) so it
// round-trips exactly through MQL5's 64-bit `long` on the #import side.
typedef long long CpuHandle;
// Lifecycle. CPU_Init(threads) always succeeds (returns a non-zero handle)
// since it needs no hardware - threads<=0 means "use
// std::thread::hardware_concurrency()". Returns 0 on failure.
WARRIORCPU_API CpuHandle __stdcall CPU_Init(int threads);
WARRIORCPU_API void __stdcall CPU_Shutdown(CpuHandle ctx);
WARRIORCPU_API int __stdcall CPU_GetLastError(CpuHandle ctx);
WARRIORCPU_API int __stdcall CPU_GetThreadCount(CpuHandle ctx);
// Stateless: true std::thread::hardware_concurrency(), independent of any
// context's pool size. Use this (not a CPU_Init(0)/GetThreadCount()/Shutdown()
// probe) to size a CPU_Init() request.
WARRIORCPU_API int __stdcall CPU_GetHardwareConcurrency();
// Buffer management. Handles are small non-negative integers scoped to ctx;
// -1 means failure. Buffers are plain double vectors owned by ctx; Write/Read
// just memcpy in/out, there is no upload/download step on CPU.
WARRIORCPU_API int __stdcall CPU_BufferCreate(CpuHandle ctx, int elementCount);
WARRIORCPU_API int __stdcall CPU_BufferWrite(CpuHandle ctx, int handle, const double *data, int count);
WARRIORCPU_API int __stdcall CPU_BufferRead(CpuHandle ctx, int handle, double *data, int count);
WARRIORCPU_API void __stdcall CPU_BufferFree(CpuHandle ctx, int handle);
// Compute kernels - argument order/semantics mirror AI\Network.cl and
// WarriorDML.h 1:1. activation: 0 = TANH, 1 = SIGMOID, 2 = PReLU (conv only).
WARRIORCPU_API int __stdcall CPU_FeedForward(CpuHandle ctx, int wHandle, int iHandle, int oHandle,
int inputs, int activation);
WARRIORCPU_API int __stdcall CPU_CalcOutputGradient(CpuHandle ctx, int tHandle, int oHandle, int igHandle,
int activation, int count);
WARRIORCPU_API int __stdcall CPU_CalcHiddenGradient(CpuHandle ctx, int wHandle, int gHandle, int oHandle, int igHandle,
int outputs, int activation, int count);
WARRIORCPU_API int __stdcall CPU_UpdateWeightsMomentum(CpuHandle ctx, int wHandle, int gHandle, int iHandle, int dwHandle,
int inputs, double learningRate, double momentum, int neurons);
WARRIORCPU_API int __stdcall CPU_UpdateWeightsAdam(CpuHandle ctx, int wHandle, int gHandle, int iHandle,
int mHandle, int vHandle,
int inputs, double lt, double b1, double b2, int neurons);
WARRIORCPU_API int __stdcall CPU_FeedForwardConv(CpuHandle ctx, int wHandle, int iHandle, int oHandle,
int inputs, int step, int windowIn, int windowOut, int activation, int positions);
WARRIORCPU_API int __stdcall CPU_CalcHiddenGradientConv(CpuHandle ctx, int wHandle, int gHandle, int oHandle, int igHandle,
int outputs, int step, int windowIn, int windowOut, int activation, int inputCount);
WARRIORCPU_API int __stdcall CPU_UpdateWeightsConvMomentum(CpuHandle ctx, int wHandle, int gHandle, int iHandle, int dwHandle,
int inputs, double learningRate, double momentum, int windowIn, int windowOut, int step);
WARRIORCPU_API int __stdcall CPU_UpdateWeightsConvAdam(CpuHandle ctx, int wHandle, int gHandle, int iHandle,
int mHandle, int vHandle,
int inputs, double lt, double b1, double b2, int windowIn, int windowOut, int step);
WARRIORCPU_API int __stdcall CPU_LSTMGates(CpuHandle ctx, int wHandle, int hiddenPrevHandle, int inputsHandle,
int concatenatedHandle, int hiddenSize, int inputSize);
WARRIORCPU_API int __stdcall CPU_LSTMState(CpuHandle ctx, int concatenatedHandle, int memoryHandle, int hiddenPrevHandle,
int hiddenCacheHandle, int outputHandle, int hiddenSize);
WARRIORCPU_API int __stdcall CPU_LSTMGateGradient(CpuHandle ctx, int gradientHandle, int memoryHandle, int concatenatedHandle,
int concatenatedGradientHandle, int hiddenSize);
WARRIORCPU_API int __stdcall CPU_LSTMWeightsGradient(CpuHandle ctx, int concatenatedGradientHandle, int hiddenCacheHandle,
int inputsHandle, int weightsGradientHandle, int hiddenSize, int inputSize);
WARRIORCPU_API int __stdcall CPU_LSTMInputsGradient(CpuHandle ctx, int concatenatedGradientHandle, int wHandle,
int inputsGradientHandle, int hiddenSize, int inputSize);
WARRIORCPU_API int __stdcall CPU_LSTMUpdateWeightsAdam(CpuHandle ctx, int wHandle, int weightsGradientHandle,
int mHandle, int vHandle, double l, double b1, double b2, int total);
WARRIORCPU_API int __stdcall CPU_LSTMUpdateWeightsMomentum(CpuHandle ctx, int wHandle, int weightsGradientHandle,
int dwHandle, double learningRate, double momentum, int total);
WARRIORCPU_API int __stdcall CPU_FeedForwardProof(CpuHandle ctx, int iHandle, int oHandle, int inputs, int window, int step, int outputs);
WARRIORCPU_API int __stdcall CPU_CalcInputGradientProof(CpuHandle ctx, int iHandle, int gHandle, int oHandle, int igHandle,
int outputs, int window, int step, int inputs);