Errores, fallos, preguntas - página 2160

 
Andrey Khatimlianskii:

Desde el punto de vista de MQ, aparentemente de forma correcta. Como siempre, decide por nosotros lo que es más conveniente.

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

No hay mensajes en mi perfil.

Renat Fatkhullin, 2018.03.08 10:31

Se ha eliminado temporalmente para reducir la cantidad de funciones que funcionan en modo de compatibilidad.

Añadiremos nuevas funciones tan pronto como se complete el proceso de migración.

Se trata de un nuevo sistema muy amplio y rico en funciones.


Se están introduciendo nuevas salas de chat.

 
Andrey Khatimlianskii:

Desde el punto de vista de MQ, aparentemente de forma correcta. Como siempre, decidió por nosotros cómo estar más cómodos.

Pasando al nivel de telepatía... )))))

 

Error poco claro en el indicador principal. Aparece sólo en los marcos de tiempo por debajo de H1, y sólo en el inicio de la terminal. Texto de error "S-v5 (EURUSD,M10) array out of range in 'S-v5.mq5' (211,54)" . El dibujo es correcto, pero en orden inverso, aunque la bandera de la serie temporal está activada para todos los búferes.

La composición de la plantilla - el indicador principal (# 1) (donde se produce el error), indicador adicional (# 2) (combinación de varias asas del indicador principal con diferentes parámetros (marco de tiempo), indicador (# 3) que muestra flechas en el gráfico principal en las señales del indicador # 1), indicador (# 4) que muestra flechas en el gráfico principal en las señales del indicador # 2.

Al cambiar de marco temporal, al volver a aplicar la plantilla, si se eliminan 2 indicadores cualquiera de 2 a 4 o sólo en el número 1, la salida de un nuevo símbolo de la visión general del mercado y la aplicación de esta plantilla - el error no se reproduce y la representación de todos los indicadores es correcta.

 

Error de compilación

#import "Test1.ex5"
       void f1();
#import "Test2.dll"
       void f2();
#import
typedef void (*fn)();
void OnStart()
{
    fn fn1 =        f1; //нормально
    fn fn2 =        f2; //Error: 'f2' - pointer to this function type is not supported yet
    fn fn3 = Test2::f2; //нормально
}
 

El mensaje de error no permite entender la causa en el código extenso

struct A {
    void f( int    ) {}
    void g( int fn ) { f( fn ); } //Error: ')' - unexpected token ???
};
typedef void (*fn)();

a continuación está claro

struct A {
    void f( int    ) {}
    void g( int fn ) { f( fn ); } //Error: 'fn' - identifier already used
};
struct fn {};
 

No hay mensaje de error

typedef void (*fn)();
void f( int i ) { Print( __FUNCTION__, ":", i ); }
void OnStart()
{
    f( fn() );
}

además, está en marcha e incluso hay un resultado (!)

En esta variante:

typedef int (*fn)();
void OnStart() { Print( fn() ); }

no se salta a la línea de error (por Enter)


 

Error de compilación

    void g(  int ) {}
    void g( uint ) {}
#import "Test.ex5"
    void f(  int );
    void f( uint );
#import
typedef void (*fn1)(  int );
typedef void (*fn2)( uint );
void OnStart()
{
    fn1 g1 = g; /*нормально и результат*/ g1( 1 ); //совпадает с ожидаемым
    fn2 g2 = g; /*нормально и результат*/ g2( 1 ); //совпадает с ожидаемым
    fn1 f1 = f; //Error: 'f' - cannot resolve function address
    fn2 f2 = f; /*нормально и результат*/ f2( 1 ); //совпадает с ожидаемым
                                                   //при наличии Test.ex5
}
 

En un intento de acelerar las cosas cuando estaba creando este ejemplo, me encontré con una rareza completamente por accidente, que simplemente puse en el estante.

Y ahora, cuando intenté lidiar con esta rareza, me confundí aún más.

Así, en el cálculo utilizo la función de raíz cuadrada sqrt(), que decidí obviar creando un array doble.

Como siempre saco la raíz cuadrada de los enteros, la creación de un array se ve así:

   double SQRT[];
   int ss=Width*Width+Height*Height;
   ArrayResize(SQRT,ss);
   for(double w=0;w<ss;w++) SQRT[(int)w]=sqrt(w);

Es lógico suponer que la lectura de la matriz SQRT[x] es más rápida que el uso de la función sqrt(x).
Y esto lo confirma el código de comprobación:

   double Sum1=0,Sum2=0;
   ulong t=GetMicrosecondCount();
   for(int i=0;i<ss;i++) Sum1+=sqrt(double(i));   // Находим сумму квадратных корней всех целых чисел от 0 до ss
   t=GetMicrosecondCount()-t;
   Print("Время на сумму "+IntegerToString(ss)+" значений функций = "+IntegerToString(t)+" мкс, Сумма = "+DoubleToString(Sum1));
   t=GetMicrosecondCount();
   for(int i=0;i<ss;i++) Sum2+=SQRT[(int)(i)];    // Находим сумму квадратных корней всех целых чисел от 0 до ss через сложение элементов массива SQRT[]
   t=GetMicrosecondCount()-t;
   Print("Время на сумму "+IntegerToString(ss)+" значений массива = "+IntegerToString(t)+" мкс, Сумма = "+DoubleToString(Sum2));

el resultado muestra una ganancia de velocidad de ~1,5 veces:

Pero cuando reemplazo la función sqrt() en el código con la lectura de los elementos del array SQRT[], en lugar de acelerar, obtengo terribles retrasos.

La lectura de un elemento de la matriz SQRT[] tarda muchas veces, quizás incluso un orden de magnitud más que la ejecución de sqrt().

Y no entiendo dónde se produce la fuga de velocidad. El código de comprobación de arriba te dice lo contrario.

Podemos suponer que el compilador accede a un array grande de alguna manera extraña y parece "olvidarse" de él en cada vuelta de bucle y realiza su propio servicio de indexación cada vez.

Pero esto es un error lógico o estratégico del compilador. Y evidentemente deberías hacer algo al respecto porque esta fuga de velocidad es muy significativa y difícil de detectar porque no es tan evidente.

Adjunto el código del script para demostrar esta rareza.

La ejecución por defecto (arr=false) calcula sqrt(), pero cuando se cambia arr a true, el valor de la raíz cuadrada se toma del array.

¿QUÉ PASA? ¿POR QUÉ ES LENTO?

Archivos adjuntos:
Swirl.mq5  11 kb
 
Nikolai Semko:

En un intento de acelerar las cosas, al crear este ejemplo, me encontré con una rareza completamente por accidente, que simplemente archivé.


Es lógico suponer que leer del array SQRT[x] es más rápido que tomar sqrt(x).

De un conjunto dinámico, no es un hecho.

Además, la toma de la raíz ya está en marcha a nivel del comando del procesador SQRTSD. Es decir, no se puede superar la implementación del procesador utilizando el notorio coste de acceso en un array dinámico.


Y esto se confirma con el código de verificación:

el resultado muestra una ganancia de velocidad de ~1,5 veces:

Dudo que esté confirmado.

El código de este tipo parece sacado de un libro de texto sobre optimización de bucles. El optimizador de código podría hacer un caramelo porque es un caso muy simple:

   for(int i=0;i<ss;i++) 
      Sum2+=SQRT[i];

Es decir, la medición del rendimiento en el caso de la aplicación de los casos deliberadamente optimizados debe estar claramente relacionada con los objetivos de la prueba.

La prueba en este caso es errónea.

Se tarda muchas veces, quizás incluso un orden de magnitud más en leer un elemento de la arraya SQRT[] que en realizar la función sqrt().

Y no entiendo dónde se produce la fuga de velocidad. Después de todo, el código de prueba anterior dice lo contrario.

Sin ver el código ensamblador final, me inclino por:

  1. sqrt es realmente rápido (tenemos un generador muy eficiente a código nativo, sqrt se convierte en puro SQRTSD)
  2. el código del verificador es demasiado simple y compensa los retrasos optimizando


Revisemos todo el código con cuidado. Es interesante averiguar cuál es la verdadera razón.

SQRTSD — Compute Square Root of Scalar Double-Precision Floating-Point Value
  • www.felixcloutier.com
Computes square root of the low double-precision floating-point value in xmm3/m64 and stores the results in xmm1 under writemask k1. Also, upper double-precision floating-point value (bits[127:64]) from xmm2 is copied to xmm1[127:64].
 
Renat Fatkhullin:

De un conjunto dinámico, no de un hecho.


Sin ver el código ensamblador final, me inclino por:

  1. sqrt es realmente rápido (tenemos un generador muy eficiente en código nativo, sqrt se convierte en puro SQRTSD)
  2. El código del verificador es demasiado simple y compensa los retrasos optimizando

Probé con una matriz estática - lo mismo.

Por muy rápido que sea sqrt, me cuesta creer que esta función pueda ser 10 veces más rápida que la simple lectura de un elemento del array.

Además, si en mi ejemplo se reduce el tamaño del lienzo, digamos 50x50 (hay un parámetro de entrada Tamaño para esto, hay que poner 50 en lugar de 0),

y la matriz será mucho más pequeña (5000 elementos), el panorama de la velocidad cambia drásticamente. Ya no hay un contraste tan fuerte.

Pero no entiendo: ¿el tamaño del array afecta a la velocidad de acceso a sus elementos?

Tal vez tengas razón en cuanto a la simplicidad del código de comprobación.

Intenté hacerlo un poco más complicado y el resultado es completamente diferente:

for(int i=0;i<ss;i++) Sum1+=i*sqrt(double(i));
....
for(int i=0;i<ss;i++) Sum2+=i* SQRT[(int)(i)];