Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[Delphi] wstawienie instrukcji przyspieszających spowalnia..

Integers 17 Wrz 2010 20:02 813 4
  • #1 17 Wrz 2010 20:02
    Integers
    Poziom 13  

    Witam.

    Code:
    procedure TObRG.Obszar_SzukajAll(_BmpRGB: TBitmap);
    
    var
      X, Y: Integer;
      X3: Integer;

      p,p1,p2: pbytearray;
      ws1, ws2:^Byte;
      r,g,b: Byte;

    begin
      _BmpRGB.PixelFormat:= pf24bit;
      FBmpPrev.Assign(_BmpRGB);

      // Szukanie od góry początkÓW obszarÓW, z pominięciem pixela ramki -----------
      Y:= 1; // 0
      Repeat
        p:= FBmpPrev.Scanline[y];         // żródło

        X:= 1; // 0
        Repeat
          x3:= x shl 2;  Inc(x3, x);

          // pobieranie wartości pierwszej składowej koloru
           // b:= p[x3];
           Inc(x3);
           g:= p[x3]; Inc(x3);
           r:= p[x3]; //Inc(x3);
          //if not Point_Tlo(r,     g,       b) then Obszar_WyznaczOne(x, y);

          // jeśli to nie punkty tła
          if (r=255) or (g=255) then Obszar_WyznaczOne(x, y);

          Inc(X, cSz2ObszIncX);
        Until (X>= FBmpPrev.Width-2); // -1
        Inc(Y, cSz2ObszIncY);

      Until (Y>= FBmpPrev.Height-2); // -1

      fmMain.MInf.Lines.Add('  obsz '+IntToStr(FLsOb.cnt));

    end;


    W jednej główniejszej procedurze stosuję "sztuczki" z

    Code:
     x3:= x shl 2;  Inc(x3, x);
    
    oraz
           Inc(x3);
           g:= p[x3]; Inc(x3);
           r:= p[x3]; //Inc(x3);


    i dajie mi to zysk z ~850 msec na ~320msec na całym działaniu kodu a jak ten sam trick zastosuje w innej pod-procedurze to czas mi się wydłuża z tych ~320 na ~1400.

    różnica jest taka że w kodzie procedury dla przypadku ~320 zmienna x3 i x jest zadeklarowana w procedurze a dla procedury ~1400 x jest parametrem wejściowym - o ile to powinno mieć jakieś znaczenie.

    Czy ktoś wie skąd się takie niekorzystne różnice w czasie przeciwne do zamierzonych biorą?

    ------------------------
    Temat poprawiłem, walczę z procedurą zaraz zaprezentuje chyba że się okaże że się pomyliłem.. to też zaprezentuje. Arty czytałem dlatego też kolejno przebudowuje procedurki.

    0 4
  • #3 17 Wrz 2010 22:56
    Integers
    Poziom 13  

    Obawiam się ze ja coś namieszałem bo procedura po podrasowaniu nie spełnia funkcji.

    Wersja działającą dobrze:

    Code:
    procedure TObRG.Obszar_SzukajAll(_BmpRGB: TBitmap);
    
    var
      X, Y: Integer;
      X3: Integer;
      p: pbytearray;

      Width3, Height3: Integer;

    begin
      _BmpRGB.PixelFormat:= pf24bit;
      FBmpPrev.Assign(_BmpRGB);

      Width3 := FBmpPrev.Width-3;
      Height3:= FBmpPrev.Height-3;

      // Szukanie od góry początkÓW obszarÓW, z pominięciem pixela ramki -----------
      Y:= 1; // 0
      Repeat
        p:= FBmpPrev.Scanline[y];         // żródło

        X:= 1; // 0
        Repeat
          x3:= x shl 2;  Inc(x3, x);


          // jeśli to nie punkty tła
          // if (r=255) or (g=255) then Obszar_WyznaczOne(x, y);
          if (p[x3+2]=255) or (p[x3+1]=255)   then Obszar_WyznaczOne(x, y);

          Inc(X, cSz2ObszIncX);
        Until (X>Width3);

        Inc(Y, cSz2ObszIncY);
      Until (Y> Height3);

      fmMain.MInf.Lines.Add('  obsz '+IntToStr(FLsOb.cnt));

    end;



    Wersja podrasowana z błędem którego nie mogę zlokalizować a on zapewne wydłuża czas trwania procedury.

    Code:
    procedure TObRG.Obszar_SzukajAll(_BmpRGB: TBitmap);
    
    var
      X, Y: Integer;
      X3: Integer;
      // p: pbytearray;
      r,g,b: Byte;
      WidthX3, Height3: Integer;
      X3cSz2ObszIncX: Integer;
      IndSpr: Integer;    // Nr sprawdzanego pola
      Wsk: ^Byte;
    begin
      _BmpRGB.PixelFormat:= pf24bit;
      FBmpPrev.Assign(_BmpRGB);

      //Width3 := FBmpPrev.Width-3;
      WidthX3 := (FBmpPrev.Width-3) *3;

      Height3:= FBmpPrev.Height-3;

      X3cSz2ObszIncX:= cSz2ObszIncX*3;

      // Szukanie od góry początkÓW obszarÓW, z pominięciem pixela ramki -----------
      Y:= 1; // 0
      Repeat
        Wsk:= FBmpPrev.Scanline[y];         // żródło

        X:= 1; // 0
        Inc(Wsk, 3);
        Repeat
          // x3:= x shl 2;  Inc(x3, x);

                    Inc(Wsk, 1); // b
          g:= Wsk^; Inc(Wsk);
          r:= Wsk^; Inc(Wsk);


          // jeśli to nie punkty tła
          // if (p[x3+2]=255) or (p[x3+1]=255) then Obszar_WyznaczOne(x, y);
          if (r=255) or (g=255) then Obszar_WyznaczOne(x, y);




          // Inc(X, cSz2ObszIncX);
          Inc(X, X3cSz2ObszIncX);
        Until (X>WidthX3);

        Inc(Y, cSz2ObszIncY);
      Until (Y> Height3);

      fmMain.MInf.Lines.Add('  obsz '+IntToStr(FLsOb.cnt));

    end;

    0
  • #4 18 Wrz 2010 08:55
    Dżyszla
    Poziom 42  

    Code:
      WidthX3 := (FBmpPrev.Width-3) *3;

    nie rozumiem, dlaczego *3 robisz szerokość pomniejszoną o 3? To tak, jakbyś uciął 3 piksele i nastęnie pomnożył razy ilosć barw. Chyba chciałeś ...*3-3 ?

    Code:
        Inc(Wsk, 3);
    Czemu od razu o 3 zwiększasz? Pomijasz umyślnie jeden piksel?

    Lewy:
    Code:
          x3:= x shl 2;  Inc(x3, x);
    A czemu tu miało służyć mnożenie przez 4? Oba zapisy są nietożsame przed i po zmianie.

    Prawy:
    Code:
          Inc(X, X3cSz2ObszIncX);
    CZemu najpierw zmienną do porównań mnożysz *3 a teraz skaczesz o 3 zmienną licznikową? To zaciemnianie kodu!

    I na koniec źródło problemów:
    X3cSz2ObszIncX:= cSz2ObszIncX*3; Ta zmienna jest niezainicjowana!


    Myślę, że przesadziłeś i to grubo z ilością zmiennych. Wyjdź od jak najbardziej czytelnego kodu a następnie krok po kroku dokonuj kolejnych optymalizacji. Czytałeś ten artykuł, który podałem? Jest tam kilka waznych ogólnych wskazówek, jak dokonywać (wszelakich) optymalizacji, których się nie trzymasz, stąd problemy.

    0
  • #5 18 Wrz 2010 10:29
    Integers
    Poziom 13  

    Tamte zmienne były zainicjowane - chodziło o skoki co kilka pixeli, a po trafieniu na punkty nie należacze do tła wyszukuje już co jeden pixel.

    Pomijam po jednym pikxelu na obwodzie, żeby przy wypełnieniu/ szukaniu uniknąć sprawdzania warunków przy pixelach brzegowych - zakładam że to przyspieszy program?.

    Faktycznie, miało być:

    Code:
    x3:= x shl 1;  Inc(x3, x); // x3:= x*3
    

    Dziękuję to był ten błąd.

    0