hafızaya array gibi erişmek
Forum kuralları
Forum kurallarını okuyup, uyunuz!
Forum kurallarını okuyup, uyunuz!
hafızaya array gibi erişmek
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.
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.
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 :
bu şekilde yapabilirsiniz. İlk aklıma gelen böyle bir yöntem
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;
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,
değiştirip biraz daha performanslı hale getirebilirsiniz. Tabi burda 0'dan başlatarak konumlanıyoruz.
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);
Ş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];
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];
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...
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...
Rica ederim.sobakava yazdı:cok tesekkur ederim, ileride de cok isime yarayacak.

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.bir de gordugum kadari ile matrisim transpoze edilmis halde memory'de duruyor, yaniliyor muyum? yani x ve y'lerin yerini degistirmek gerekiyor?
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...

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;
Kod: Tümünü seç
MatrixElemanVer(matrixim,9,2,3,sizeof(word))^
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;
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?
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ışıyorsobakava yazdı: matrixim degiskeni olarak hafizada verilerin basladigi adresin pointer'ini mi verecegim?

Evet silersin öyle kullanılabilir.dizi indisleri 0 yerine 1'den baslayacak anladigim kadari ile? sub EAX,1'leri silsem 0'dan baslayan dizi indisleri kullanabilirim 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.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?
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;
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...bir de fonksiyonu typecasting yapmadan direkt olarak word tanimlamak bir hiz artisi saglar mi?
Kolay gelsin...
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....
Kolay gelsin....
Arkadaşlar hiç boşuna assembler kasmayın. Yukarıda açıkladığım yöntem ile bir deneme kodu yazarsak:
ve muhteşem Delphi compiler'ının assembler çıktısına bakarsak:
kodu için:
ü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.
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;
Kod: Tümünü seç
Value:= P16X16_WordArray(Address)^[I][0];
Kod: Tümünü seç
mov eax,ebx
shl eax,2
mov edx, [ebp-4]
mov si, [edx+eax*8]
Kodun okunabilirliğini arttıracak yegane yöntem budur. Assembler yapmanız halinde kaydadeğer bir performans artışı olacağını da zannetmiyorum.
