Erros, bugs, perguntas - página 2160

 
Andrey Khatimlianskii:

Do ponto de vista da MQ, aparentemente correctamente. Como sempre, decidiu por nós o que é mais conveniente.

Fórum sobre comércio, sistemas comerciais automatizados e teste de estratégias comerciais

Não há mensagens no meu perfil.

Renat Fatkhullin, 2018.03.08 10:31

Removido temporariamente para reduzir a quantidade de funcionalidade a trabalhar em modo de compatibilidade.

Acrescentaremos novas funcionalidades assim que o processo de migração estiver concluído.

Este é um novo sistema muito grande e rico em características.


Estão a ser introduzidas novas salas de chat.

 
Andrey Khatimlianskii:

Do ponto de vista da MQ, aparentemente correctamente. Como sempre, decidimos por nós como estar mais confortáveis.

Passando ao nível do telepático... )))))

 

Insecto pouco claro no indicador principal. Aparece apenas nos prazos abaixo de H1, e apenas no arranque do terminal. Texto de erro "S-v5 (EURUSD,M10) array fora do intervalo em 'S-v5.mq5' (211,54)" . O desenho está correcto, mas em ordem inversa, embora a bandeira da série cronológica esteja definida para todos os amortecedores.

A composição do modelo - o indicador principal (#1) (onde o erro ocorre), indicador adicional (#2) (combinação de várias pegas do indicador principal com parâmetros diferentes (período de tempo), indicador (#3) que exibe setas no gráfico principal sobre os sinais do indicador #1), indicador (#4) que exibe setas no gráfico principal sobre os sinais do indicador #2.

Alternando o período de tempo, reaplicando o modelo, se remover quaisquer 2 indicadores de 2 para 4 ou apenas no número 1, a saída de um novo símbolo da visão geral do mercado e aplicação deste modelo - o erro não é reproduzido e a renderização de todos os indicadores está correcta.

 

Erro de compilação

#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; //нормально
}
 

A mensagem de erro não permite que a causa seja compreendida no extenso código

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

abaixo é claro

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

Nenhuma mensagem de erro

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

além disso, está a funcionar e há mesmo um resultado (!)

Nesta variante:

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

nenhum salto para a linha de erro (por Enter)


 

Erro de compilação

    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
}
 

Numa tentativa de acelerar as coisas quando estava a criar este exemplo, deparei-me com uma estranheza completamente por acidente, que acabei de colocar na prateleira.

E agora, quando tentei lidar com esta estranheza, fiquei ainda mais confuso.

Assim, no cálculo utilizo a função raiz quadrada sqrt(), que decidi contornar, criando uma dupla matriz.

Uma vez que retiro sempre a raiz quadrada dos inteiros, criar uma matriz parece-se com isto:

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

É lógico supor que a leitura a partir da matriz SQRT[x] é mais rápida do que a utilização da função sqrt(x).
E isto é confirmado pelo código de verificação:

   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));

o resultado mostra um ganho de velocidade de ~1,5 vezes:

Mas quando substituo a função sqrt() no código pela leitura dos elementos da matriz SQRT[], em vez de acelerar, recebo terríveis atrasos.

A leitura de um item da matriz SQRT[] demora muitas vezes, talvez até uma ordem de magnitude mais longa do que correr sqrt().

E não compreendo onde ocorre a fuga de velocidade. O código de verificação acima diz-lhe o contrário.

Podemos supor que o compilador acede de alguma forma estranha a uma grande variedade e parece "esquecê-lo" em cada volta do laço e executa o seu próprio serviço de indexação de cada vez.

Mas isto é ou um bug lógico ou um bug de compilação estratégico. E deve obviamente fazer algo quanto a isso porque esta fuga de velocidade é muito significativa e difícil de detectar porque não é tão óbvia.

Estou a anexar o código do guião para demonstrar esta estranheza.

A execução padrão (arr=false) calcula sqrt(), mas quando se muda arr para verdadeiro, o valor da raiz quadrada é retirado do array.

O QUE É ERRADO? PORQUE É LENTO?

Arquivos anexados:
Swirl.mq5  11 kb
 
Nikolai Semko:

Numa tentativa de acelerar as coisas, ao criar este exemplo, deparei-me com uma estranheza completamente por acidente, que acabei de arquivar.


É lógico assumir que a leitura a partir da matriz SQRT[x] é mais rápida do que tomar sqrt(x).

A partir de uma matriz dinâmica, não é um facto.

Além disso, a tomada da raiz já se encontra no nível de comando do processador SQRTSD. Ou seja, não se pode vencer a implementação do processador utilizando o notório custo de acesso numa matriz dinâmica.


E isto é confirmado pelo código de verificação:

o resultado mostra um ganho de velocidade de ~1,5 vezes:

Duvido que seja confirmado.

O código deste tipo é como algo saído de um livro de texto sobre optimização de loops. O optimizador de código pode fazer dele um doce porque é um caso muito simples:

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

Ou seja, a medição do desempenho no caso de aplicação dos casos deliberadamente optimizados tem de estar claramente relacionada com os objectivos do teste.

O teste, neste caso, está errado.

Demora muitas vezes, talvez até uma ordem de magnitude mais longa a ler um item do arraya SQRT[] do que a executar a função sqrt().

E não percebo onde ocorre a fuga de velocidade. Afinal de contas, o código de teste acima diz o contrário.

Sem ver o código final do montador, inclino-me para ele:

  1. sqrt é realmente rápido (temos um gerador muito eficiente para código nativo, sqrt transforma-se em puro SQRTSD)
  2. o código do verificador é demasiado simples e compensa os atrasos através da optimização


Vamos verificar cuidadosamente todo o código. É interessante descobrir qual é a verdadeira razão.

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:

A partir de uma matriz dinâmica, não é um facto.


Sem ver o código final do montador, inclino-me para ele:

  1. sqrt é realmente rápido (temos um gerador muito eficiente em código nativo, sqrt transforma-se em puro SQRTSD)
  2. O código do verificador é demasiado simples e compensa os atrasos através da optimização

Experimentei uma matriz estática - a mesma coisa.

Por mais rápido que seja o sqrt, tenho dificuldade em acreditar que esta função possa ser 10 vezes mais rápida do que apenas ler um elemento de matriz.

Além disso, se no meu exemplo o tamanho da tela for reduzido, digamos 50x50 (para isto há um parâmetro de entrada Tamanho, é necessário definir 50 em vez de 0),

e a matriz será muito mais pequena (5000 elementos), o quadro da velocidade muda drasticamente. Já não existe um contraste tão forte.

Mas não compreendo: o tamanho da matriz afecta a velocidade de acesso aos seus artigos?

Talvez tenha razão sobre a simplicidade do código de verificação.

Tentei torná-lo um pouco mais complicado e o resultado é 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)];