//+------------------------------------------------------------------+ //| MatMulBench.mq5 | //| Benchmark: matrix nativo vs manual vs array | //+------------------------------------------------------------------+ #property copyright "Benchmark" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| 1) Multiplicación MANUAL usando el tipo matrix (indexado a mano) | //+------------------------------------------------------------------+ bool MatMulManual(const matrix &A, const matrix &B, matrix &C) { ulong n = A.Rows(); ulong k = A.Cols(); ulong m = B.Cols(); if(B.Rows() != k) return false; C = matrix::Zeros(n, m); for(ulong i = 0; i < n; i++) { for(ulong j = 0; j < m; j++) { double sum = 0.0; for(ulong p = 0; p < k; p++) sum += A[i][p] * B[p][j]; C[i][j] = sum; } } return true; } //+------------------------------------------------------------------+ //| 2) Multiplicación NATIVA (operador MatMul de matrix) | //+------------------------------------------------------------------+ bool MatMulNative(const matrix &A, const matrix &B, matrix &C) { C = A.MatMul(B); return true; } //+------------------------------------------------------------------+ //| 3) Multiplicación emulando matrix con double[] planos (row-major)| //+------------------------------------------------------------------+ bool MatMulArray(const double &A[], const double &B[], double &C[], int n, int k, int m) { ArrayResize(C, (int)(n * m)); ArrayInitialize(C, 0.0); for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { double sum = 0.0; int aBase = i * k; for(int p = 0; p < k; p++) sum += A[aBase + p] * B[p * m + j]; C[i * m + j] = sum; } } return true; } //+------------------------------------------------------------------+ //| Helpers para llenar con datos aleatorios | //+------------------------------------------------------------------+ matrix RandMatrix(ulong rows, ulong cols) { matrix m(rows, cols); for(ulong i = 0; i < rows; i++) for(ulong j = 0; j < cols; j++) m[i][j] = (double)MathRand() / 32767.0; return m; } void RandArray(double &arr[], int n, int m) { ArrayResize(arr, n * m); for(int i = 0; i < n * m; i++) arr[i] = (double)MathRand() / 32767.0; } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { const int N = 600; // dimensión de las matrices NxN const int ITER = 300; // repeticiones MathSrand(42); //--- Preparar datos base (matrix) matrix Am = RandMatrix(N, N); matrix Bm = RandMatrix(N, N); //--- Preparar datos base (array plano) double Aa[], Ba[]; ArrayResize(Aa, N * N); ArrayResize(Ba, N * N); for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) { Aa[i * N + j] = Am[i][j]; Ba[i * N + j] = Bm[i][j]; } double checksum = 0.0; //=== 1) Manual con matrix === { matrix C; ulong a = GetMicrosecondCount(); for(int it = 0; it < ITER; it++) { MatMulManual(Am, Bm, C); checksum += C[0][0]; } ulong b = GetMicrosecondCount(); Print("1) Manual (matrix indexado): ", (b - a), " us checksum=", checksum); } //=== 2) Nativo MatMul === { matrix C; checksum = 0.0; ulong a = GetMicrosecondCount(); for(int it = 0; it < ITER; it++) { MatMulNative(Am, Bm, C); checksum += C[0][0]; } ulong b = GetMicrosecondCount(); Print("2) Nativo (A.MatMul(B)): ", (b - a), " us checksum=", checksum); } //=== 3) Emulado con double[] === { double C[]; checksum = 0.0; ulong a = GetMicrosecondCount(); for(int it = 0; it < ITER; it++) { MatMulArray(Aa, Ba, C, N, N, N); checksum += C[0]; } ulong b = GetMicrosecondCount(); Print("3) Array double[] (row-major):", (b - a), " us checksum=", checksum); } } //+------------------------------------------------------------------+