2017-11-17 95 views
7

chciałbym złożyć następujące emitowany pracę wyrażenie:Zmiana kształtu nadawanego wyraz

J = rand(4,4) 
fx1 = rand(2,2) 
fx2 = rand(2,2) 
@. J[:,1] = fx1 + fx2 

naprawdę ma jakieś:

@. J[:,1] = vec(fx1 + fx2) 

gdzie to vec mówi powinno przekształcić się 4x1 , ale nie chcę tego alokować. W jaki sposób można to zrobić w sposób ogólny (tzn. Bez indeksowania na fx)?

+1

Co na temat '@. J [:, 1] = vec (fx1) + vec (fx2) '? Mogłoby to w zasadzie przydzielić dwa tymczasowe pliki, ale zakładam, że jest to wystarczająco łatwe, aby kompilator mógł się pozbyć. – gTcV

Odpowiedz

3

Inną możliwością jest zamiast vec -ing z fx1 i fx2 do przekształcenia plasterka J:

Jcol = reshape(view(J,:,1),(2,2)) 
@. Jcol = fx1 + fx2 

Nie jestem pewien co do wydajności, ale może to dać wyraźniejszą perspektywę w zależności od algorytmu otoczenia. Kod LLVM wydaje się wystarczająco krótki, a instrukcja przypisania jest jasna.

+0

Używanie BenchmarkTools '@btime @. Jcol = fx1 + fx2' daje 0 przydziałów. –

+2

Dobra uwaga. Możesz po prostu użyć 'reshape' tutaj - powinien zawsze zwracać" widok ". W rzeczywistości, jako ostateczna permutacja, myślę, że możesz również wyrazić to jako '@. J [zmiana kształtu (1: 4, 2, 2), 1)] = fx1 + fx2 ". Teoretycznie może to być ta sama wydajność, ale nie dysponujemy wszystkimi optymalizacjami w zakresie wykorzystania zmienionych zakresów jako indeksów, więc na razie będzie to wolniejsze. –

+0

Zaktualizowano za pomocą prostszego "przekształcenia" –

2

Ponieważ komisje, są widoki, następujące prace:

J = rand(4,4) 
fx1 = rand(2,2) 
fx2 = rand(2,2) 
vfx1,vfx2 = vec(fx1),vec(fx2) 
@. J[:,1] = vfx1 + vfx2 

Nie sądzę, istnieje sposób, aby to zrobić w jednej linii tak jak chciałem, ale to jest w porządku.

3

Można „zwolniony” vec od @. makro chroniąc go z $:

julia> expand(:(@. J[:,1] = $vec(fx1) + $vec(fx2))) 
:((Base.broadcast!)(+, (Base.dotview)(J, :, 1), (vec)(fx1), (vec)(fx2)))