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] przepisywanie adresów zmiennych typów np. rekordowy

Integers 09 Wrz 2010 16:49 1598 11
  • #1 09 Wrz 2010 16:49
    Integers
    Poziom 13  

    Witam.

    Mam pytanie, gdzieś widziałem taki sposób ale powtórne odszukanie niestety zakończyło się niepowodzeniem, a może porostu nie mogę znaleźć bo się nie da... ,ale do rzeczy.

    mam

    Code:

    typ
       TRec = record
         ...
       end;
       TTabRec = array[0..100] of TRec;

    var
       ListaRec: TTabRec;
       tmpRec: TRec;


    Obliczenia wykonuję na tmpRec i jeśli zdecyduje że się nadaje do zapisania na ListaRec to zamiast przekopiowywać kolejno składowe (a są bardzo rozbudowane) chciałbym sprubować zamienić adresy pamieci albo coś w tym stylu;
    np.
    Adr1:= AdresWPamieci ListaRec[15] // jest akurat pusty
    Adrt: = AdresWPamieci tmpRec // już wypełniony danymi

    ListaRec[15] podczepienie adresu Adrt
    tmpRec podczepienie adresu Adr1

    Chyba że jest inny sposób na tego typu podmianki?

    0 11
  • #2 09 Wrz 2010 17:40
    arnoldziq
    Moderator Programowanie

    Spróbuj zadeklarować TObject zamiast rekordu, a te obiekty umieszczać jako elementy TList.
    To powinno rozwiązać wiele z twoich problemów. Możesz dane sortować, usuwać z listy puste obiekty, dodawać nowe i nie musisz się martwić, że ci się rozmiar tablicy wyczerpie.
    Masz tutaj przykładowy kod takiej struktury wraz z kilkoma metodami.

    Code:
    unit NewTagList;
    
    interface
    uses
      Classes, SysUtils;
    type
      TTagListItem = class(TObject)
        ItemID         : integer;
        GroupID        : Integer;
        Name           : string;
        Time           : TDateTime;
       [...]
      end; {class}

      TTagList = class(TObject)
      private
        fItems:TList;
      public
        constructor Create;
        destructor Destroy; override;
        procedure Clear;
        function Count:integer;
        function AddNew( ItemID, GroupID : integer; Name:string ):TTagListItem;
        function ItemByID( ItemID:integer ):TTagListItem;
        function ItemByIDandGroup( ItemID,GroupID : integer ):TTagListItem;
        function Items( Index:Integer):TTagListItem;
        procedure SortByItemID;
        procedure SortByName;
        procedure SortByTime;

      end; {class}

    implementation
    function _ItemCompareItemID( Item1,Item2:Pointer ):integer;
    var
      TagListItem1,TagListItem2:TTagListItem;
    begin
      TagListItem1 := TTagListItem(Item1);
      TagListItem2 := TTagListItem(Item2);
      if (TagListItem1.ItemID < TagListItem2.ItemID) then begin
        Result := -1;
        Exit;
      end; {if}
      if (TagListItem1.ItemID > TagListItem2.ItemID) then begin
        Result := +1;
        Exit;
      end; {if}
      Result := AnsiCompareStr( TagListItem1.Name, TagListItem2.Name );
    end;

    function _ItemCompareName( Item1,Item2:Pointer ):integer;
    var
      TagListItem1,TagListItem2:TTagListItem;
    begin
      TagListItem1 := TTagListItem(Item1);
      TagListItem2 := TTagListItem(Item2);
      Result := AnsiCompareStr( TagListItem1.Name, TagListItem2.Name );
      if (Result <> 0) then Exit;
      if (TagListItem1.ItemID < TagListItem2.ItemID) then begin




        Result := -1;
        Exit;
      end; {if}
      if (TagListItem1.ItemID > TagListItem2.ItemID) then begin
        Result := +1;
        Exit;
      end; {if}
    end;

    function _ItemCompareTime( Item1,Item2:Pointer ):integer;
    var
      TagListItem1,TagListItem2:TTagListItem;
    begin
      TagListItem1 := TTagListItem(Item1);
      TagListItem2 := TTagListItem(Item2);
      Result := CompareDateTimes( TagListItem1.Time, TagListItem2.Time );
      if (Result = 0) then Result := AnsiCompareStr( TagListItem1.Name, TagListItem2.Name );
    end;

    constructor TTagList.Create;
    begin
      fItems := TList.Create;
    end;

    destructor TTagList.Destroy;
    begin
      Clear;
      fItems.Free;
    end;

    procedure TTagList.Clear;
    var
      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        TTagListItem(fItems[idx]).Free;
      end; {for}
      fItems.Clear;
    end;

    function TTagList.Count:integer;
    begin
      Result := fItems.Count;
    end;

    function TTagList.AddNew( ItemID, GroupID : integer; Name:string ):TTagListItem;
    begin
      if GroupID=0 then Result := ItemByID( ItemID )
      else Result := ItemByIDandGroup( ItemID, GroupID );
      if (Result = NIL) then
      begin
        Result := TTagListItem.Create;
        Result.ItemID := ItemID;
        Result.Name := Name;
        Result.Time := now;
        fItems.Add(Result);
      end; {if}
    end;

    function TTagList.AddItem( ItemID:integer; Name:string ):TTagListItem;
    begin
      Result:=AddItemWithGroup( ItemID,0,Name);
    end;

    function TTagList.ItemByIDandGroup( ItemID,GroupID : integer ):TTagListItem;
    var
      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        Result := TTagListItem(fItems[idx]);
        if (Result.ItemID = ItemID) and ((Result.GroupID = GroupID)) then Exit;
      end; {for}
      Result := NIL;
    end;

    function TTagList.ItemByID( ItemID:integer ):TTagListItem;
    var
      idx:integer;
    begin
      for idx := 0 to (fItems.Count-1) do begin
        Result := TTagListItem(fItems[idx]);
        if (Result.ItemID = ItemID) then Exit;
      end; {for}
      Result := NIL;
    end;

    function TTagList.Items( Index:integer ):TTagListItem;
    begin
      Result := TTagListItem(fItems[index]);
    end;

    procedure TTagList.SortByItemID;
    begin
      fItems.Sort( _ItemCompareItemID );
    end;

    procedure TTagList.SortByName;
    begin
      fItems.Sort( _ItemCompareName );
    end;

    procedure TTagList.SortByTime;
    begin
      fItems.Sort( _ItemCompareTime );
    end;
    end.

    0
  • #3 09 Wrz 2010 18:26
    Integers
    Poziom 13  

    Ok. Dzięki, bo sposób jest interesujący i warto się takowego nauczyć, jednak jak wygląda sprawa z prędkością podmiany danych, ewentualnie dodanie danych do listy.

    Pytam bo u mnie jest trochę więcej danych i chce wycisnąć jak najmniejszy czas, trochę skrócona wersja

    Code:

    type
       cPointMax = 2000000;
       TTbPoint = array[0..cPointMax] of TPoint;
       PTbPoint = ^TTbPoint;

       TObsz = record
         rgb: TRGBTriple;          // kolor szukanej plamy
         tab: TTbPoint;            // tablica punktów
         cnt: Integer;             // licznik startuje od zera
         LColor: Integer;
         x1, y1,                   // zakres obszaru
         x2, y2: Integer;
       end;
       PObsz = ^TObsz;

       TArrayObsz = array of TObsz;
       TListObsz = record
         rgb: TRGBTriple;          // kolor szukanej plamy
         arr: TArrayObsz;          // tablica obszarów
         cnt: Integer;             // licznik startuje od zera
       end;
       PListObsz = ^TListObsz;



    i chodzi mi oto żeby na dobrą sprawę operować na adresach rekordów, gdyż baaaardzo zależy mi na skróceniu czasu, wiem ze można dobierać się do adresów stałych i podmieniać im wartości w trakcie działania programu więc może i tu się taka sztuczka uda.
    Jesli by sie dało to zastosowałbym zarówno na swojej jaki i na Twojej arnoldziq strukturze.

    W tej chwili mam czas wykonania operacji wyszukiwania, dodawania, +-1000 msec, a chce to skrócić do 100 msec. nie stosowałem jeszcze pętli asembler-owych żeby potem móc się odnaleźć, na razie poprawiam jakby od końca od strony algorytmu i operacji na danych.

    Żeby było śmieszniej to algorytm przeszukiwania/wypełniania wierszami miał być wydajniejszy a właśnie przez ilość operacji i czas ich trwania nie widać różnicy miedzy nim a wyszukiwaniem pożarowym.

    0
  • #4 10 Wrz 2010 10:27
    arnoldziq
    Moderator Programowanie

    Oczywiście, że użycie klas zajmie więcej czasu procesora niż tworzenie i operacje na rekordach umieszczonych w pamięci.

    Twoja deklaracja polega na rekordach wskaźników, wskazujących na inne wskaźniki i zmiany adresów tych wskaźników mogą być naprawdę szybkie, ale czy przemyślałeś operację przydzielania pamięci do zmiennych na które te wskaźniki mają wskazywać ?
    Patrząc na twój kod deklaracji, nie mogę się doczekać aż zamieścisz jakąś procedurę, która będzie operować na tych danych.

    Zadeklaruj, proszę, także wszystkie zmienne dla typu PListObsz i sprawdź ile miejsca to zajmie w pamięci.

    0
  • #5 10 Wrz 2010 10:49
    Integers
    Poziom 13  

    no to teraz dostałem po nosie :), faktycznie klasy są wygodne w użyciu ale obsługa ich wydłuża pracę :(

    no nic pozostaje mi przerobić wszystko od zera i zadeklarować typy jako zmienne globalne, ale z drugiej strony chciałem operacje na jednej bitmapie włożyć do wątku o podwyższonym priorytecie i sprawdzić czy zyskam w ten sposób na szybkości.

    Co do kodu to sam w sobie nie jest skomplikowany bo to zwykłe operacje na bitmapie i tabeli rekordów, spróbuje podzielić tablice na dynamiczne segmenty może to zmniejszy ilość miejsca.

    Przy uruchomieniu 33 444KB,
    obsługa tej listy od 340-520MB zależny w której fazie
    - sprawdzałem z poziomu menagera zadań

    0
  • #6 10 Wrz 2010 11:56
    arnoldziq
    Moderator Programowanie

    Integers napisał:
    no to teraz dostałem po nosie :),
    Nie :), nie chodzi o to żeby cię zniechęcać.
    Integers napisał:
    z drugiej strony chciałem operacje na jednej bitmapie włożyć do wątku o podwyższonym priorytecie i sprawdzić czy zyskam w ten sposób na szybkości.
    Nic nie stoi na przeszkodzie.
    Integers napisał:
    Co do kodu to sam w sobie nie jest skomplikowany bo to zwykłe operacje na bitmapie i tabeli rekordów, spróbuje podzielić tablice na dynamiczne segmenty może to zmniejszy ilość miejsca.
    Czemu nie wgrasz takiej bitmapy do jakiegoś strumienia i nie operujesz na nim, tylko uparłeś się żeby trzymać w pamięci tablicę punktów ?
    Integers napisał:
    Przy uruchomieniu 33 444KB, obsługa tej listy od 340-520MB
    Przerażasz mnie !!!! :)

    Może napisz po prostu, co chcesz osiągnąć, może ktoś podpowie łatwiejszy (prostszy, mniej pamięciożerny) sposób.

    0
  • #7 10 Wrz 2010 12:09
    Integers
    Poziom 13  

    Nie zniechęciłem się, chodziło mi o to że zapomniałem o prostszych ekonomiczniejszych rozwiązaniach, a co do strumieni jeszcze ich nie umiem ale skoro mogą pomóc to czas się nauczyć.

    Z ta obsługa listy to jest tak, klasa po uruchomieniu zawiera w sobie bitmapę która obrabia, czyli np mamy film z klatką/bitmapą co 30msec i zostaje tworzona klaska która dostaje bitmapę do swojej pamięci i ją obrabia,

    dla jasności

    Code:
    Przy uruchomieniu 33 444KB, obsługa tej listy od 340-520MB 

    dotyczy operacji na jednej bitmapie, jak uda mi się osiągnąć szybszy, mniej pamięciożerny sposób wtedy to wezmę się za obróbkę danych w tabeli.
    Jak na razie czas jest przerażający ...

    0
  • #8 11 Wrz 2010 09:56
    Integers
    Poziom 13  

    arnoldziq próbuję jeszcze zrobić taki manewr w Twoim TTagListItem
    żeby pobrać adresy/wskaźniki na dany rekord/obiekt rekordowy i zamieniać adresy między nazwami, wczoraj zamieściłem ten pomysł żeby operować na czystych rekordach ale google milczy na ten temat więc może przynajmniej z obiektami się tak da. Podmianka adresów była by szybsza niż przepisywanie wartości na piechotę, o ile jest taka możliwość.

    0
  • #9 13 Wrz 2010 10:22
    arnoldziq
    Moderator Programowanie

    Integers napisał:
    wczoraj zamieściłem ten pomysł żeby operować na czystych rekordach ale google milczy na ten temat
    Bo praktycznie od czasów OOP w BP7 nikt tego nie robi, chyba, że w celach szkoleniowych.
    Integers napisał:
    więc może przynajmniej z obiektami się tak da. Podmianka adresów była by szybsza niż przepisywanie wartości na piechotę, o ile jest taka możliwość.
    W obiektach nie ma mowy o przepisywaniu wartości. Operujesz tylko na wskaźnikach do nich.

    Opisz jeszcze raz, co próbujesz zrobić, bo z dotychczasowych opisów, nie jestem (może to tylko ja? :) ) w stanie wywnioskować o co dokładnie chodzi. Zrozumiałem że chcesz obrabiać w jakiś sposób filmy w czasie rzeczywistym. Proszę, powiedz dokładnie co chcesz zrobić i dlaczego zależy ci na obrabianiu każdej klatki z osobna ?

    0
  • #10 13 Wrz 2010 11:10
    Integers
    Poziom 13  

    A więc po kolei:
    Mam już prawie skończone operacje na bitmapie (obróbka skalowanie) nie jest to jeszcze super szybkie bo przydało by się to w asemblerze zrobić niestety nie znam nikogo komu mógłbym to zlecić, wiec to musi poczekać aż się nauczę.
    Tak czy owak efektem końcowym są większe plamy w jednolitym kolorze np kolorze zbliżonym do skóry dłoni.

    Ja teraz potrzebuje super szybkiego wyszukiwania i wypełniania dużych plam, czyli:
    - oznaczenie Pixel tła czarny lub różowy (oznacza sprawdzony)
    - w pętli skaczę co dx=10, dy=10 sprawdzam pixel tła to nic,
    a jak nie tła to znaczy, że jakiś obszar więc sprawdzam jak jest rozległy,
    ile ma pikseli, jaki kolor

    i do tego potrzebna mi jest szybka lista, żebym
    - mógł szybko posortować od największego do najmniejszego - wiem ze do tego mógłbym po prostu użyć listy z nr indeksów ale...
    - szybkie przenoszenie danych do zmiennej pomocniczej żebym mógł wykonywać inne operacje nie bezpośrednio na licie,

    ale to opisałem jak sobie wyobrażam a co bym chciał osiągnąć?

    Włączam kamerkę internetową, na razie mam podgląd a nie bezpośredni przechwyt obrazu, macham sobie ręką przed kamerą a program przechwytuje screenem obraz i w podglądzie zarysowuje plamę dłoni która się przemieszcza w lewo i w prawo, w górę i w dół.

    To tak najprościej a potem rozszerzę o inne możliwości. dlatego zależy mi na tym aby wszystko nadążało za klatką filmu bo potem będzie bezpośrednio obraz szedł z kamery, a jeszcze musi być czas na wykonanie obliczeń, np. ręka symulująca odbijanie piłki na ekranie.

    przy okazji zamiana w kodzie z div na shr dała mi 4-5msec zysku na jednej bitmapie 1280x960 pomniejszona 4 razy

    Code:
    var   wsk: ^Byte;
    
       bt: Byte;

    begin      if wsk^ > 127
            then bt := TLib_IntToByte(wsk^ + (Abs(127-wsk^)*AmountC) div 255)
            else bt := TLib_IntToByte(wsk^ - (Abs(127-wsk^)*AmountC) div 255);

          if wsk^ > 127
            then bt := TLib_IntToByte(wsk^ + (Abs(127-wsk^)*AmountC) shr 8)
            else bt := TLib_IntToByte(wsk^ - (Abs(127-wsk^)*AmountC) shr 8);

    da się to jeszcze jakoś skrócić? bo przy operacjach na samej bitmapie mam 32 msec, wiec liczy się każde przyspieszenie

    0
  • #11 13 Wrz 2010 12:03
    arnoldziq
    Moderator Programowanie

    No, to teraz mam jasność to do twoich założeń... które są całkowicie błędne.
    Jeżeli chcesz rozpoznawać ruch w obrazie z kamerki internetowej, to pozostaje mi powiedzieć : "pełen czacun" :)
    Zamiast "wymyślać koło" zainteresuj się tematem : Zastosowanie sieci neuronowych w rozpoznawaniu obrazów.
    Problem jest dość znany i chociaż dość skomplikowany w realizacji, to jednak życzę ci powodzenia.

    0
  • #12 13 Wrz 2010 12:23
    Integers
    Poziom 13  

    myślałem o sieciach i jakieś wstępne rozpoznawanie zrobiłem ale najpierw chcę spróbować bez gdyż mi nie jest potrzebne rozpoznawanie jako takie tylko szybkość przemieszczania się plamy dłoni czyli na dobrą sprawę tylko różnicę w pozycji miedzy między kolejnymi klatkami, sieć jako taka też nie jest aż tak szybka i trzeba jej niektóre dane podać na patelni.

    Mi wystarczy że będę znał przybliżony środek plamy, a to już mam, potem i tak muszę przekształcić obraz na mapę bitową czyli obecność danego koloru na fotce, wyciągnąć współrzędne środków plam, bo sieć jest szybka gdy plama jest jednego kształtu np. kołem ale jeśli zadam jej 50 różnych kształtów to staje się nieprecyzyjna i wymaga rozbudowania... chyba ze coś nie doczytałem ...

    w skrócie czas potrzebny na przetworzenie danych na potrzeby sieci jest taki sam jak przetworzenia który ja chce wykonać, z tym ze potem sieć trzeba uczyć i odpowiedni patrzeć a ja mam poprzez wypełnienie gotowe współrzędne które mi już mówią wszystko szukam tylko szybszego sposobu algorytmu bo szkielet już jest a teraz kolejno wymieniam procedury na szybsze.

    No i sieć budowałbym rok :) a na razie chcę mieć jakiś efekt już teraz żeby wyprowadzić kolejne wyliczenia

    0