Erros, bugs, perguntas - página 2161

 
Renat Fatkhullin:


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

Fixe! Obrigado! Eu também estou interessado.

E a sqrt é de facto muito rápida. Menos de um nanossegundo :))). Fantástico!

 
Nikolai Semko:

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.

Nesta altura, muitas das antigas técnicas de optimização já não funcionam.


Além disso, se no meu exemplo para reduzir o tamanho da tela, 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), a imagem da velocidade seria muito diferente. Já não existe um contraste tão forte.

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

Não há nenhuma prova limpa dos seus cálculos, está a fazer suposições baseadas em códigos muito sujos.

Está a negligenciar uma tonelada de cálculos auxiliares que estão no seu código e que têm um impacto significativo nos resultados.

 
Renat Fatkhullin:


Não existe uma prova limpa dos seus cálculos, está a fazer suposições baseadas em códigos muito confusos.

Está a negligenciar uma tonelada de cálculos auxiliares que estão no seu código e que têm um impacto significativo nos resultados.

Tudo o que posso ver é que apenas mudando o sqrt para uma leitura simples a partir de uma matriz, a velocidade global de cálculo cai por um factor de 4. E a proporção global de sqrt neste cálculo bastante grande de cada pixel é pouco superior a 10%, ou mesmo alguns %.

Uma anomalia clara!

Cometi até o erro de dizer que o tempo de acesso a um elemento de matriz é 10 vezes o tempo de matriz. Muito mais dado que a sqrt é tão rápida e a desaceleração geral é tão grande.

 
Nikolai Semko:

Só consigo ver que, simplesmente mudando o sqrt para uma simples leitura da matriz, a velocidade global de cálculo cai por um factor de 4. E a proporção total de sqrt neste cálculo bastante grande de cada pixel é pouco superior a 10%, ou mesmo alguns %.

Uma clara anomalia!

Já expliquei porquê. As optimizações da matemática dos anos noventa já não funcionam.

Mas continua a fazer as seguintes afirmações com base em códigos reais. Em relação às plantas, estão errados.

A este nível de [un]pureza técnica não vou discutir as questões.

 
Renat Fatkhullin:

Já expliquei porquê. As optimizações da matemática dos anos noventa já não funcionam.

Mas continua a fazer as seguintes afirmações com base em código realmente conspurcado. Plausivelmente defeituosa.

A este nível de [un]pureza técnica não vou discutir as questões.

Não compreendo de que optimização matemática está a falar. E eu não estava a fazer qualquer afirmação, apenas a pensar qual seria a fonte dos travões.

Onde está a desordem e optimização neste código original?

#include <Canvas\Canvas.mqh>

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // получаем Ширину окна
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // получаем Высоту окна
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // создаем канвас размером текущего окна
   Print("Error creating canvas: ",GetLastError()); 
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[25600];
   for (int w=0;w<25600;w++) 
   h[w]= uchar(128+128*sin(double(w)/256));//создаем массив для ускорения работы
   double X1=0,Y1=0,X2=0,Y2=0,X3=0,Y3=0,X4=0,Y4=0;
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         //Sleep(30);
         X1= Width/2-(sin((double)j/100)*(double)Width/2);
         Y1= Height/2-(cos((double)j/140)*(double)Height/2);
         X2= Width/2+(cos((double)j/80)*(double)Width/2);
         Y2= Height/2+(sin((double)j/20)*(double)Height/2);
         X3= Width/2+(cos((double)j/85)*(double)Width/2);
         Y3= Height/2+(sin((double)j/65)*(double)Height/2);
         X4= Width/2+(cos((double)j/152)*(double)Width/2);
         Y4= Height/2+(sin((double)j/42)*(double)Height/2);
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);
      double D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));
      double D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
      double D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));
      double D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));
      double d= (D1+D2)/(D1+D2+D3+D4);
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }

Pode utilizar este código mais genérico, mas graças à utilização de loops e arrays a velocidade de enquadramento de imagem é quase reduzida para metade:

#include <Canvas\Canvas.mqh>
#property script_show_inputs 
input int N=8; // количество центов гравитации

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // get Window width
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // get Window height 
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // create canvas with the size of the current window
      Print("Error creating canvas: ",GetLastError());
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[];
   ArrayResize(h,25600);
   for(int w=0;w<25600;w++) h[w]=uchar(128+128*sin(double(w)/256)); //create an array to speed up the work
                                                                  
   int k[]; ArrayResize(k,N*2);
   for(int w=0;w<N*2;w++) k[w]=20+rand()%200;
   double XP[],YP[],D[],D1[];
   ArrayResize(XP,N);
   ArrayResize(YP,N);
   ArrayResize(D,N);
   ArrayInitialize(XP,0);
   ArrayInitialize(YP,0);
  
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         for(int w=0;w<N;w++)
           {
            XP[w]= Width/2-(sin((double)j/k[2*w])*(double)Width/2);
            YP[w]= Height/2-(cos((double)j/k[2*w+1])*(double)Height/2);
           }
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);

      for(int w=0;w<N;w++) D[w]= sqrt((XP[w]-X)*(XP[w]-X)+(YP[w]-Y)*(YP[w]-Y));
      double S1=0,S2=0;
      for(int w=0;w<N/2;w++) S1+=D[w];
      for(int w=0;w<N;w++) S2+=D[w];
      double d=S1/S2;
      
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }
//+------------------------------------------------------------------+
 

Optimizar a matemática: tentar utilizar arrays em vez de sqrt.

Não se vê a confusão e isto é a raiz da sua má compreensão das regras de testes de desempenho. Se testar a matriz pré-calculada versus cálculo, terá de remover tudo o que é supérfluo. Absolutamente tudo o que é desnecessário.

Tem feito muitas afirmações. É necessário poder ler os textos do lado do destinatário e limpá-los das defesas não trabalhadoras do autor.

 
Renat Fatkhullin:

Optimização da matemática: tentar utilizar arrays em vez de sqrt.

Oh, que se lixe a sqrt. Já percebi que, no caso desta função em particular, não faz sentido. O que há de errado em tentar? Mas agora eu sei-o.

A propósito, a utilização da matriz h[] nesta amostra também dá um ganho de velocidade considerável em vez de utilizar sin().

A questão é sobre outra coisa:

Porque é que a utilização do acesso a células de uma grande variedade aumenta o tempo de cálculo em várias vezes, quando se esperava apenas alguns por cento?

Não se vê a ninhada e essa é a raiz da sua má compreensão das regras de testes de desempenho.Se estiver a testar a matriz pré-calculada versus cálculo, terá de remover tudo o que é supérfluo. Absolutamente tudo o que é desnecessário.

Sabes, Renat, não é uma vergonha receber uma bofetada de ti, mas até uma honra.

Pelo que sei, o lixo é algo desnecessário que pode e deve ser removido. Mas neste caso não há nada para limpar senão o código deixará de funcionar.

Não estou a testar"matriz pré-calculada versus cálculo", mas sim a analisar a velocidade de formação da moldura.

No meu caso, não preciso de testes, porque tenho um portátil fraco e consigo ver a diferença entre 25 fps e 6 fps sem qualquer teste.

As afirmações que fez são maciças. É necessário poder ler os textos do lado do destinatário e libertá-los das defesas não trabalhadoras do autor.

Só fiz algumas suposições, não afirmações:

- "É lógico assumir que a leitura da matriz SQRT[x] é mais rápida do que a função sqrt(x)".

-"Poder-se-ia supor que o compilador está a aceder a uma grande matriz de alguma forma estranha, e a cada volta do laço parece "esquecer" a matriz e fazer algum tipo de indexação de serviço de cada vez. "

Mas ainda me atrevo a fazer esta afirmação porque embora seja um programador autodidacta, mas autodidacta com grande experiência e compreendo algo sobre processos dentro do processador, porque houve um tempo em que o meu programa favorito era o Numega SoftIce, através do qual escavei toneladas de código extraterrestre a nível de assembler.

- Asseguro-lhe que existe um bug algorítmico no seu compilador, relativo ao acesso a arrays, (talvez apareça apenas com um array suficientemente grande), que a sua equipa encontrará facilmente, se colocar vector de esforço nesta direcção. E o meu exemplo vai ajudar-vos.

Poderia até argumentar. ))

 

Quando se faz um loop através de uma tabela, cada vez que se acede a ela a seguir, é provável que ela esteja na cache do processador. É por isso que corre mais depressa.

Se houver algum código entre os acessos, é provável que haja uma falha de cache. Isto também explica a diferença no manuseamento de uma mesa grande e pequena.

Além disso, existem outros casos não óbvios. Por conseguinte, é necessário testar a versão final não simplificada do código.

 
Rapazes, como podem dizer nos modelos de funções que uma função com o tipo enumeração foi chamada?
 
Vladimir Pastushak:
Os rapazes dizem-me como nos modelos de função para determinar que a função com enumeração de tipo é chamada???
enumeração é uma enumeração inteira.
0,1,2,3 ..., etc....