hafızaya array gibi erişmek

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
sobakava
Üye
Mesajlar: 14
Kayıt: 19 Tem 2003 04:16

hafızaya array gibi erişmek

Mesaj gönderen sobakava »

arkadaslar,

hafizada belli bir yerde matris seklinde bir veri var elimde, baslagic adresi B diyelim (longint) ve herbiri word olmak uzere 256 tane veri var.

normalde

pw : pword;
dt : word;
----------------

for i:=1 to 256 do
begin
pw:= ptr( b);
dt := pw^;
inc(b);
end;

diyerekten tum word'leri okuyabiliyorum. ama ben baslangici B olan ve 16x16 = 256 byte olan bu veriye, dizi indeksi kullanarak ulasmak istiyorum:

myarray: array[1..16, 1..16] of word;


...
..
dt:=myarray[5,9]; şeklinde mesela


bunun için bir şekile dinamik bir dizi tanımlayıp, başlangıç adresinin B olduğunu söylemem gerekiyor. bunu nasıl yaparım fikri olan var mı?

şu an yaptığım metodla word word okuyup bir diziye atıp oradan çalışmak da geldi aklıma ama performans kaybı oluyor çünkü bu işlemi tekrarlayan bi şekilde defalarca hızlı bir şekilde yapmam gerekiyor.

şimdiden teşekkürler.
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

Merhaba,

Matrisi, ilk 16 elemanı birinci satırı, ikinci 16 elamanı ikinci satırı ifade edilecek şekilde bir array olarak saklıyorsunuz ama satır ve sütün belirterek istediğiniz girdiye ulaşmak istiyorsunuz.

Array'in ilk elemanının adresi B değişkeni ile gösteriliyorsa :

Kod: Tümünü seç

function get(satir,sutun:integer):word;
var
 X : PWord;
begin 
  X := B;
  Inc(X,16*(satir-1)+sutun);
  Result := X^;
end;
bu şekilde yapabilirsiniz. İlk aklıma gelen böyle bir yöntem
sobakava
Üye
Mesajlar: 14
Kayıt: 19 Tem 2003 04:16

Mesaj gönderen sobakava »

daha hızlı bir metod yok mudur? her eleman icin bir adet carpma islemi yapmak gerekecek bu sekilde.

MATRIS 16x16 elemanlı WORD dizidir, başlangıç adresi de B olsun deyip belirttiğim hafıza adresinden sonrasına dizi gibi erişmenin bir yolu yok mu?
t-hex
Kıdemli Üye
Mesajlar: 531
Kayıt: 18 Mar 2005 02:45
Konum: İstanbul/Antalya
İletişim:

Mesaj gönderen t-hex »

Merhaba,

Bildiğim kadarıyla 16x16 WORD array tanımladığınızda bu array'in elemanları hafızada yanyana ayrılıyor. Yani :

arr[1,1] dizinin 17. elemanını gösterir.

Çarpma işleminden kurtulmak için şunu önerebilirim:

Eğer Matris ebatları hep 2'nin katları şeklindeyse,

Kod: Tümünü seç

Inc(X,(satir shl 4) + sutun); 
değiştirip biraz daha performanslı hale getirebilirsiniz. Tabi burda 0'dan başlatarak konumlanıyoruz.
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Şu şekilde ulaşabilirsin:

Kod: Tümünü seç

type
  PWordArray = ^TWordArray;
  TWordArray = array[0..255] of Word;
var
  Address: Longint;
  Value: Word;
begin
  // Bu senin B dediğin adres olsun.
  Address:= $12323321;
  // Burada 122 indexli değeri Value'ya atıyoruz.
  Value:= PWordArray(Address)^[122];
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Aynı şekilde 16x16 elemanlı ve Word içeren bir diziyi:

Kod: Tümünü seç

type
  P16X16_WordArray = ^T16X16_WordArray;
  T16X16_WordArray = array[0..15, 0..15] of Word;
var
  Address: Longint;
  Value: Word;
begin
  // Bu senin B dediğin adres olsun.
  Address:= $12323321;
  // Burada 1'e 12 indexli değeri Value'ya atıyoruz.
  Value:= P16X16_WordArray(Address)^[1][12];
sobakava
Üye
Mesajlar: 14
Kayıt: 19 Tem 2003 04:16

Mesaj gönderen sobakava »

codelord, soyledigin metod da calisti bir cevrimim 78'den 31 ms'ye indi. ayrica cok guzel, bu sekilde bir kullanim oldugunu bilmiyordum. cok tesekkur ederim, ileride de cok isime yarayacak.

bir de gordugum kadari ile matrisim transpoze edilmis halde memory'de duruyor, yaniliyor muyum? yani x ve y'lerin yerini degistirmek gerekiyor?


axy :

a11 a21 a31 a41
a12 a22 a32 a42
a13 a23 a33 a43

seklindeki bir matrise

myarray(b)^[x,y] diye degil y,x diye erisince dogru elemanlara erisebiliyorum.... diger turlu yan yatmis oluyor veri matrisi...
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

sobakava yazdı:cok tesekkur ederim, ileride de cok isime yarayacak.
Rica ederim. :)
bir de gordugum kadari ile matrisim transpoze edilmis halde memory'de duruyor, yaniliyor muyum? yani x ve y'lerin yerini degistirmek gerekiyor?
Belleğe atarken nasıl bir yöntem izlediğini bilemediğim için net bir cevap veremiyorum. Belleğe atarken de bu type'ı (T16X16_WordArray) kullanırsan standart bir işlem yapmış olursun. Yazma ve okuma işlemlerin kolaylaşır.
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

Biraz olayını b.kunu çıkartmak gibi olacak ama şu yöntem belki daha hızlı olabilir. Test etmek lazım ;)

Bu arada X sütun, Y satır. Bu asm fonksiyonuyla herhangi bir hafıza bölgesindeki ardışık veriyi matrix şeklinde alabilirsiniz. İster word halinde, ister byte halinde. Ancak kullandığınız veri tipinin büyüklüğünü parametre olarak geçirmelisiniz. Ayrıca satır sınırlamasıda yok. Sadece matrixwidth ile sütun sayısını vermeniz gerekir.

not : Kodlar araklama değil benim uğraşımdır.

Kolay gelsin...

Kod: Tümünü seç

var
var
  Form1: TForm1;
  matrixim:array [0..99] of word;
implementation

{$R *.dfm}

function MatrixElemanVer(const matrix;x,y,matrixwidth,typesize:integer):pointer; stdcall;
begin
 asm
   mov EAX, X
   sub EAX, 1
   mul EAX, matrixwidth
   add EAX, Y
   sub EAX, 1
   mul EAX, typesize
   add EAX, matrix
   mov @result, eax
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i:integer;
begin

  for i := 0 to 99 do
  begin
    matrixim[i] := word(i) + 1;
  end;

  showmessage(inttostr(word(MatrixElemanVer(matrixim,9,2,3,sizeof(word))^)));

end;

Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

Bu arada ben örnek olsun diye bir array verdim fonksiyona. İlla array kullanmanıza gerek yok. Herhangi bir hafıza bölgesinin pointerını bilmeniz yeterli.
sobakava
Üye
Mesajlar: 14
Kayıt: 19 Tem 2003 04:16

Mesaj gönderen sobakava »

Kod: Tümünü seç

   MatrixElemanVer(matrixim,9,2,3,sizeof(word))^
 
matrixim degiskeni olarak hafizada verilerin basladigi adresin pointer'ini mi verecegim?

Kod: Tümünü seç

function MatrixElemanVer(const matrix;x,y,matrixwidth,typesize:integer):pointer; stdcall; 
begin 
 asm 
   mov EAX, X 
   sub EAX, 1 
   mul EAX, matrixwidth 
   add EAX, Y 
   sub EAX, 1 
   mul EAX, typesize 
   add EAX, matrix 
   mov @result, eax 
 end; 
end; 
dizi indisleri 0 yerine 1'den baslayacak anladigim kadari ile? sub EAX,1'leri silsem 0'dan baslayan dizi indisleri kullanabilirim oyle degil mi?

ayrica matrixwidth (16 veya 1392) ve typesize (2) sabit oldugu icin bunlari da parametre olarak aktarmak yerine kodda yazmaz isterim. ornegin typesize icin EAX yazmaci ile typesize'i carpmak yerine EAX'i bir kez sola shift etsem yeterli olacaktir oyle degil mi?


bir de fonksiyonu typecasting yapmadan direkt olarak word tanimlamak bir hiz artisi saglar mi?
Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can »

Şu function ve procedure leri araştırınız:

Addr()
@
Move()

İyi çalışmalar.
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

sobakava yazdı: matrixim degiskeni olarak hafizada verilerin basladigi adresin pointer'ini mi verecegim?
Evet aynen öyle. Zaten Array dediğin tip o bölgenin başlangıç adresini tutan bir değişken. En azından C'de böyle. Delphidede böyleki kod çalışıyor :)
dizi indisleri 0 yerine 1'den baslayacak anladigim kadari ile? sub EAX,1'leri silsem 0'dan baslayan dizi indisleri kullanabilirim oyle degil mi?
Evet silersin öyle kullanılabilir.
ayrica matrixwidth (16 veya 1392) ve typesize (2) sabit oldugu icin bunlari da parametre olarak aktarmak yerine kodda yazmaz isterim. ornegin typesize icin EAX yazmaci ile typesize'i carpmak yerine EAX'i bir kez sola shift etsem yeterli olacaktir oyle degil mi?
Kodu o zaman şöyle değiştir. Shift çok daha hızlı olduğu için kod hızlanıcaktır. Sadece Type size için değil matrixwidth içinde SHL kullanalım bide ordan hızlanalım.

Kod: Tümünü seç

function MatrixElemanVer2(const matrix;x,y:integer):pointer; stdcall;
begin
 asm
   mov EAX, X
   SHL EAX, 4  // eax = eax*16
   add EAX, Y
   SHL EAX, 1 // eax = eax*2
   add EAX, matrix
   mov @result, eax
 end;
end;
bir de fonksiyonu typecasting yapmadan direkt olarak word tanimlamak bir hiz artisi saglar mi?
Bence sağlamaz. Oraya Word() yazmamız derleyicinin o pointerdan başlayarak 2 byte hafızadan diğer değişkene atmasını sağlayan instructionları yazdırıyordur. Sen direk word tanımlasanda aynı iş olacak...

Kolay gelsin...
Kullanıcı avatarı
undefined
Moderator
Mesajlar: 565
Kayıt: 06 Eki 2003 12:01
Konum: Bursa
İletişim:

Mesaj gönderen undefined »

O asm kodunun herhangi bir instructionuna breakpoint koy. Programı çalıştırdığın zaman program break olunca Cpu windowunu aç. Orda compilerın asıl generate ettiği kodları görüceksin. Aslında X,y,matrix değişkenleriyle gelenler stack yoluyla geçirilmiş parametreler. Ve mov komutuyla eax'a EBP registeri yardımı ile geçirildiğini göreceksin. Eğer merakı olan varsa elimde dağtımı bedava olan güzel bir Asm referans kitabı var. Delphiyle nasıl kullanıldığınıda gösteriyor. Bunları gönderebilirim isteyene.

Kolay gelsin....
fduman
Moderator
Mesajlar: 2749
Kayıt: 17 Ara 2004 12:02
Konum: Ankara

Mesaj gönderen fduman »

Arkadaşlar hiç boşuna assembler kasmayın. Yukarıda açıkladığım yöntem ile bir deneme kodu yazarsak:

Kod: Tümünü seç

type
  P16X16_WordArray = ^T16X16_WordArray;
  T16X16_WordArray = array[0..15, 0..15] of Word;

var
  Address: Longint;
  Value: Word;
  I: Integer;
begin
  // Bu senin B dediğin adres olsun.
  Address:= $12323321;
  for I:= 0 to 15 do
  begin
    Value:= P16X16_WordArray(Address)^[I][0];
    Memo1.Lines.Add(IntToStr(Value));
  end;
end;
ve muhteşem Delphi compiler'ının assembler çıktısına bakarsak:

Kod: Tümünü seç

Value:= P16X16_WordArray(Address)^[I][0];
kodu için:

Kod: Tümünü seç

mov eax,ebx
shl eax,2
mov edx, [ebp-4]
mov si, [edx+eax*8]
ürettiğini göreceğiz.

Kodun okunabilirliğini arttıracak yegane yöntem budur. Assembler yapmanız halinde kaydadeğer bir performans artışı olacağını da zannetmiyorum. :)
Cevapla