|
Autor |
Arrayindices als Array angeben |
|
Greyfox
Ehemals Aktiv  Dabei seit: 12.08.2003 Mitteilungen: 319
Wohnort: Berlin
 | Themenstart: 2019-08-15
|
Hallo allerseits,
ich möchte ein paar langsame for-Schleifen vermeiden und brauche einen guten Tipp:
In Dimension 1 ist für mich alles gut:
Sei A=[2 3 2 3 1]
und B=[0.3 0.2 0.1]
dann ist B(A)=[0.2 0.1 0.2 0.1 0.3]
Ich kann also die Werte von A als Indices nutzen um quasi an diesen Stellen bei B nachzuschauen. (Falls die Werte von A dafür geeignet sind.)
NUN DAS PROBLEM
Ich möchte dies viermal tun, ohne Schleifen zu verwenden.
Sei also A vom Typ 2 x 2 x 5, z.B.
A(1,1,:)=[1 1 1 1 1]
A(1,2,:)=[1 1 1 1 1]
A(2,1,:)=[2 3 2 3 1]
A(2,2,:)=[3 3 3 1 1]
und
B(1,1,:)=[0.1 0.2 0.3]
B(1,2,:)=[-0.1 -0.2 -0.3]
B(2,1,:)=[0.1 0.2 0.3]
B(2,2,:)=[-0.1 -0.2 -0.3]
Dann würde ich mir wünschen, dass C=B(A) das Ergebnis
C(1,1,:)=[0.1 0.1 0.1 0.1 0.1]
C(1,2,:)=[-0.1 -0.1 -0.1 -0.1 -0.1]
C(2,1,:)=[0.2 0.3 0.2 0.3 0.1]
C(2,2,:)=[-0.3 -0.3 -0.3 -0.1 -0.1]
wäre.
Ich würde mir also wünschen, dass C(s,t,u)=B(s,t,A(s,t)) wäre.
Ist es aber nich. Stattdessen kommt
C(1,1,:)=[0.1 0.1 0.1 0.1 0.1]
C(1,2,:)=[0.1 0.1 0.1 0.1 0.1]
C(2,1,:)=[0.1 -0.1 0.1 -0.1 0.1]
C(1,1,:)=[-0.1 -0.1 -0.1 0.1 0.1]
raus.
Statt C(s,t,u)=B(s,t,A(s,t)) ist also C(s,t,u)=B(A(s,t,u)), wobei B linear durchgezählt wird. Leider muss ich zugeben, dass das ja durchaus auch Sinn macht. Wie aber bekomme ich das Array C, so wie ich es mir wünsche?
Beste Grüße
Greyfox
|
Profil
|
hyperG
Senior  Dabei seit: 03.02.2017 Mitteilungen: 2010
 | Beitrag No.1, eingetragen 2019-08-15
|
Zunächst bitte sauberen Syntax verwenden, damit alles logisch bleibt:
\sourceon Script
Nicht B(A)
sondern B(A(i))
\sourceoff
i sei der horizontale Index (immer von links nach rechts).
Dann würde ich jeden Index immer bei 0 beginnen, da sonst
"Speicherplatz" verschenkt & Geschwindigkeit verloren geht.
Die Erweiterung um 2 Dimensionen macht die ganze Sache langsamer & unübersichtlicher! Es sind eigentlich 2 Dimensionen:
A(x,i) mit x=0...3 und i= 0...4
\sourceon Script
A(0,i)=[1 1 1 1 1]
A(1,i)=[1 1 1 1 1]
A(2,i)=[2 3 2 3 1]
A(3,i)=[3 3 3 1 1]
\sourceoff
B analog.
Wenn Du unbedingt bei Deinen 3 Dimensionen A3 und dem verschobenen 1-Index bleiben willst, geht das mit dem Bezug zum 2D-Array:
\sourceon Script
A3(floor(x/2)+1,mod(x,2)+1, i+1) = A2(x,i)
\sourceoff
Nun ist alles viel einfacher: x entspricht der Zeile 0...3; i sind die 5 Werte pro Zeile, die vertauscht werden sollen
\sourceon Script
C(x,i) = B(x,A(x,i))
\sourceoff
A ist das "Vertauscher-Array", was nur Werte von 0...2 beinhaltet, da
das "Real-Array B" nur 3 Werte pro Zeile enthält.
|
Profil
|
Greyfox
Ehemals Aktiv  Dabei seit: 12.08.2003 Mitteilungen: 319
Wohnort: Berlin
 | Beitrag No.2, vom Themenstarter, eingetragen 2019-08-15
|
Hallo hyper G,
ich glaube, wir reden noch leicht aneinander vorbei. Bei manchen Dingen kann ich Dir folgen, bei manchen nicht.
Für das bessere Verständnis können wir die Dimension reduzieren. Keine Ahnung ob der Code dadurch viel schneller wird.
Mein Skript könnte also so starten:
\sourceon Script
clear all;
%declare A
A(1,:)=[1 1 1 1 1];
A(2,:)=[1 1 1 1 1];
A(3,:)=[2 3 2 3 1];
A(4,:)=[3 3 3 1 1];
%declare B
B(1,:)=[0.1 0.2 0.3];
B(2,:)=[-0.1 -0.2 -0.3];
B(3,:)=[0.1 0.2 0.3];
B(4,:)=[-0.1 -0.2 -0.3];
\sourceoff
Ich bin mir nicht ganz sicher, was Du damit meinst, dass die Indizes von 0 starten sollen, denn ich dachte immer Matlab akzeptiert nur positive Indices.
("Subscript indices must either be real positive integers or logicals.")
Tatsächlich würde ich das gewünschte Ergebnis erhalten wenn ich mein Skript wie folgt fortsetzen würde:
\sourceon Script
for x=1:4
for i=1:5
C(x,i)=B(x,A(x,i));
end
end
\sourceoff
Ich möchte aber die for-schleifen vermeiden, weil die aus meiner Sicht sehr langsam sind und die Vorteile der GPU töten. Ich kann mir vorstellen, dass arrayfun oder pagefun mir helfen könnten mit einer Funktion wie z.B.
\sourceon Script
FUN=@(x,y)(y(x));
\sourceoff
aber da kämpfe ich noch mit der Syntax um das Ziel zu erreichen.
|
Profil
|
Greyfox
Ehemals Aktiv  Dabei seit: 12.08.2003 Mitteilungen: 319
Wohnort: Berlin
 | Beitrag No.3, vom Themenstarter, eingetragen 2019-08-15
|
Okay ich habe mich doof angestellt. Hier meine Lösung mit der ich leben kann:
\sourceon Script
clear all;
%declare A
A(1,1,:)=[1 1 1 1 1];
A(1,2,:)=[1 1 1 1 1];
A(2,1,:)=[2 3 2 3 1];
A(2,2,:)=[3 3 3 1 1];
%declare B
B(1,1,:)=[0.1 0.2 0.3];
B(1,2,:)=[-0.1 -0.2 -0.3];
B(2,1,:)=[0.1 0.2 0.3];
B(2,2,:)=[-0.1 -0.2 -0.3];
%declare Array for Row-number
Row=repmat((1:2)',1,2,5);
%declare Array for Column-number
Col=repmat((1:2),2,1,5);
%declare lookup-Function
Fun=@(i,j,k)(B(i,j,k));
%Compute C
C=arrayfun(Fun,Row,Col,A);
\sourceoff
Besten Dank für den Input.
-------------------------------------------------------------------
Edit:
... dachte ich. Aber für GPU-arrays funktioniert das nicht, denn Fun ist zu komplex.
Deshalb noch ein Workaround:
\sourceon Script
clear all;
%declare A
A(1,1,:)=[1 1 1 1 1];
A(1,2,:)=[1 1 1 1 1];
A(2,1,:)=[2 3 2 3 1];
A(2,2,:)=[3 3 3 1 1];
%declare B
B(1,1,:)=[0.1 0.2 0.3];
B(1,2,:)=[-0.1 -0.2 -0.3];
B(2,1,:)=[0.1 0.2 0.3];
B(2,2,:)=[-0.1 -0.2 -0.3];
%declare Array for Row-number
Row=repmat((1:2)',1,2,5);
%declare Array for Column-number
Col=repmat((1:2),2,1,5);
%Make everything GPU-just to show that it works on GPU
A=gpuArray(A);
B=gpuArray(B);
Col=gpuArray(Col);
Row=gpuArray(Row);
%Declare a funktion that is basicly sub2ind([2,2,5],i,j,k)
%f=@(i,j,k)(sub2ind([2,2,5],i,j,k)); does not work on GPU
f=@(i,j,k)(i+(j-1)*2+(k-1)*2*2);
%Create an array of the corrected Indices:
M=arrayfun(f,Row,Col,A);
%Harvest the fruits
C=B(M);
\sourceoff
|
Profil
|
Greyfox hat die Antworten auf ihre/seine Frage gesehen. Greyfox hat selbst das Ok-Häkchen gesetzt. | Greyfox wird per Mail über neue Antworten informiert. |
|
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2001-2023 by Matroids Matheplanet
This web site was originally made with PHP-Nuke, a former web portal system written in PHP that seems no longer to be maintained nor supported. PHP-Nuke is Free Software released under the GNU/GPL license.
Ich distanziere mich von rechtswidrigen oder anstößigen Inhalten, die sich trotz aufmerksamer Prüfung hinter hier verwendeten Links verbergen mögen. Lesen Sie die
Nutzungsbedingungen,
die Distanzierung,
die Datenschutzerklärung und das Impressum.
[Seitenanfang]
|