matlab - Efficient Multiplication of Matrices with Large Numbers of Zeroes -
i have 2 arrays take following form:
0…0…0 0 0 0…0 0…0…0 0 0 0…0 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ 0…0 0 0 0 0…0 0…0 0 0 0 0…0 = 0…0 1 2 3 0…0 b = 0…0 9 8 7 0…0 0…0 4 5 6 0…0 0…0 6 5 4 0…0 0…0 0 0 0 0…0 0…0 0 0 0 0…0 ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ 0…0…0 0 0 0…0 0…0…0 0 0 0…0
the size of non-zero areas of a
, b
may not same, diagram above getting bit unwieldy.
ultimately, value i'm after sum(sum(a .* b))
. feel there must way multiply non-zero elements, every approach can come seems cause matlab make copy of matrix, utterly destroys gains made reducing number of operations. b
reused several iterations of inner loop, can amortize expensive calculations on b
on many loop iterations.
i've tried following approaches far:
naive approach:
function c = innerloop(a, b) c = sum(sum(a .* b)) end
innerloop
takes 4.3 seconds on 86,000 calls using this. (based on matlab's "run , time" functionality.)
shrinking b
first:
function b = resize(self, b1) rows = abs(sum(b, 2)) > 1e-4; top = find(rows, 1, 'first'); bot = find(rows, 1, 'last'); cols = abs(sum(b, 1)) > 1e-4; left = find(cols, 1, 'first'); right = find(cols, 1, 'last'); self.rows = top:bot; % store in class properties use in inner loop self.cols = left:right; % store in class properties use in inner loop b = b(top:bot, left:right); end function c = innerloop(a, b) result = a(self.rows, self.cols) .* b; c = sum(sum(result)); end
my hope approach matlab realize wasn't writing a
, elide copy, approach spends 6.8 seconds in innerloop
.
i tried calculation offsets outside innerloop
in hopes matlab might able pick on fact i'm using same subscripts on both matrices optimize things:
function b = resize(self, b1) rows = abs(sum(b, 2)) > 1e-4; top = find(rows, 1, 'first'); bot = find(rows, 1, 'last'); cols = abs(sum(b, 1)) > 1e-4; left = find(cols, 1, 'first'); right = find(cols, 1, 'last'); self.rows = top:bot; % store in class properties use in inner loop self.cols = left:right; % store in class properties use in inner loop end function c = innerloop(a, b) result = a(self.rows, self.cols) .* b(self.rows, self.cols); c = sum(sum(result)); end
unfortunately slowest yet @ 8.6 seconds.
i tried looping following code:
function c = innerloop(a, b) c = 0; = self.rows j = self.cols c = c + field(i, j) * self.sensitivity.z(i, j); end end end
i know looping used slow in matlab, i've read papers indicating faster used be. said, if loop version ever finishes running, i'll let know how long took, it's on couple minutes now.
any suggestions on how optimize appreciated!
you can use sparse matrices problem. matlab handles different sizes of «non-sparse-part» automatically. sparse matrix, sparse
-function used. after can element-wise multiplication , sum elements of c
in separate line.
a = [0 0 0 0 0 0 0; 0 0 0 0 0 0 0; 0 0 1 2 3 0 0; 0 0 4 5 6 0 0; 0 0 0 0 0 0 0; 0 0 0 0 0 0 0]; b = [0 0 0 0 0 0 0; 0 0 0 0 0 0 0; 0 0 9 8 7 0 0; 0 0 6 5 4 0 0; 0 0 0 0 0 0 0; 0 0 0 0 0 0 0]; = sparse(a); b = sparse(b); c = .* b; sum(c(:))
Comments
Post a Comment