简体   繁体   English

MATLAB中无循环的矩阵计算

[英]Matrix calculations without loops in MATLAB

I have an issue with a code performing some array operations. 我对执行一些数组操作的代码有问题。 It is too slow, because I use loops and input data are quite big. 这太慢了,因为我使用循环并且输入数据很大。 It was the easiest way for me, but now I am looking for something faster than for loops. 这对我来说是最简单的方法,但是现在我正在寻找比循环更快的东西。 I was trying to optimize or rewrite code, but unsuccessful. 我试图优化或重写代码,但未成功。 I really aprecciate Your help. 我真的很感谢您的帮助。

In my code I have three arrays x1 , y1 (coordinates of points in grid), g1 (values in the points) and for example their size is 300 x 300. I treat each matrix as composition of 9 and I make calculation for points in the middle one. 在我的代码中,我有三个数组x1y1 (网格中的点的坐标), g1 (点中的值),例如,它们的大小为300 x300。我将每个矩阵视为9的组成,并对点中的点进行计算中间一个。 For example I start with g1(101,101) , but I am using data from g1(1:201,1:201)=g2 . 例如,我从g1(101,101) ,但是我使用的是g1(1:201,1:201)=g2 I need to calculate distance from each point of g1(1:201,1:201) to g1(101,101) ( ll matrix), then I calculate nn as it is in the code, next I find value for g1(101,101) from nn and put it in N array. 我需要计算从g1(1:201,1:201)g1(101,101)ll矩阵)的每个点的距离,然后按代码中的原样计算nn,接下来我g1(101,101)找到g1(101,101)值nn并将其放在N数组中。 Then I go to g1(101,102) and so on until g1(200,200) , where in this last case g2=g1(99:300,99:300) . 然后我转到g1(101,102) ,依此类推,直到g1(200,200) ,在这种情况下, g2=g1(99:300,99:300)

As i said, this code is not very efficient, even I have to use larger arrays than I gave in the example, it takes too much time. 就像我说的那样,此代码不是很有效,即使我必须使用比示例中给出的数组更大的数组,这也花费了太多时间。 I hope I explain enough clearly what I expect from the code. 我希望我能足够清楚地解释我对代码的期望。 I was thinking of using arrayfun, but I have never worked with this function, so I don't know how should use it, however it seems to me it won't handle. 我当时在考虑使用arrayfun,但是我从未使用过此功能,因此我不知道该如何使用它,但是在我看来,它将无法处理。 Maybe there are other solutions, however I couldn't find anything apropriate. 也许还有其他解决方案,但是我找不到合适的解决方案。

tic
x1=randn(300,300);
y1=randn(300,300);
g1=randn(300,300);
m=size(g1,1);
n=size(g1,2);
w=1/3*m;
k=1/3*n;
N=zeros(w,k);
for i=w+1:2*w 
    for j=k+1:2*k 
        x=x1(i,j);
        y=y1(i,j);
        x2=y1(i-k:i+k,j-w:j+w);
        y2=y1(i-k:i+k,j-w:j+w);
        g2=g1(i-k:i+k,j-w:j+w);
        ll=1./sqrt((x2-x).^2+(y2-y).^2);
        ll(isinf(ll))=0;
        nn=ifft2(fft2(g2).*fft2(ll));
        N(i-w,j-k)=nn(w+1,k+1);
      end
  end
  czas=toc;

For what it's worth, arrayfun() is just a wrapper for a for loop, so it wouldn't lead to any performance improvements. 就其价值而言, arrayfun()只是for循环的包装,因此不会导致任何性能改进。 Also, you probably have a typo in the definition of x2 , I'll assume that it depends on x1 . 另外,您可能在x2的定义中有错别字,我假设它取决于x1 Otherwise it would be a superfluous variable. 否则它将是一个多余的变量。 Also, your i<->w/k , j<->k/w pairing seems inconsistent, you should check that as well. 另外,您的i<->w/kj<->k/w配对似乎不一致,您也应该检查一下。 Also also, just timing with tic/toc is rarely accurate. 同样 ,仅使用tic/toc计时很难准确。 When profiling your code, put it in a function and run the timing multiple times, and exclude the variable generation from the timing. 对代码进行性能分析时,请将其放入函数中并多次运行计时,并从计时中排除变量的生成。 Even better: use the built-in profiler. 更好的是:使用内置的探查器。

Disclaimer: this solution will likely not help for your actual problem due to its huge memory need. 免责声明:由于其巨大的内存需求,该解决方案可能无法解决您的实际问题。 For your input of 300x300 matrices this works with arrays of size 300x300x100x100, which is usually a no-go. 对于您输入的300x300矩阵,此格式适用于大小为300x300x100x100的数组,通常不行。 Still, it's here for reference with a smaller input size. 仍然,这里以较小的输入大小供参考。 I wanted to add a solution based on nlfilter(), but your problem seems to be too convoluted to be able to use that. 我想添加一个基于nlfilter()的解决方案,但是您的问题似乎太复杂了,无法使用它。

As always with vectorization, you can do it faster if you can spare the memory for it. 与矢量化一样,如果可以为其保留内存,则可以更快地完成此操作。 You are trying to work with matrices of size [2*k+1,2*w+1] for each [i,j] index. 您正在尝试为每个[i,j]索引使用大小为[2*k+1,2*w+1]矩阵。 This calls for 4d arrays, of shape [2*k+1,2*w+1,w,k] . 这需要形状为[2*k+1,2*w+1,w,k] 4d数组。 For each element [i,j] you have a matrix with indices [:,:,i,j] to treat together with the corresponding elements of x1 and y1 . 对于每个元素[i,j]您都有一个索引为[:,:,i,j]的矩阵,将其与x1y1的相应元素一起处理。 It also helps that fft2 accepts multidimensional arrays. 它还有助于fft2接受多维数组。

Here's what I mean: 这就是我的意思:

tic
x1 = randn(30,30);  %// smaller input for tractability
y1 = randn(30,30);
g1 = randn(30,30);
m = size(g1,1);
n = size(g1,2);
w = 1/3*m;
k = 1/3*n;

%// these will be indexed on the fly:    
%//x = x1(w+1:2*w,k+1:2*k);     %// size [w,k]
%//y = x1(w+1:2*w,k+1:2*k);     %// size [w,k]

x2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
y2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
g2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]

%// manual definition for now, maybe could be done smarter:
for ii=w+1:2*w       %// don't use i and j as variables
    for jj=k+1:2*k   %// don't use i and j as variables
        x2(:,:,ii-w,jj-k) = x1(ii-k:ii+k,jj-w:jj+w);  %// check w vs k here
        y2(:,:,ii-w,jj-k) = y1(ii-k:ii+k,jj-w:jj+w);  %// check w vs k here
        g2(:,:,ii-w,jj-k) = g1(ii-k:ii+k,jj-w:jj+w);  %// check w vs k here
    end
end

%// use bsxfun to operate on [2*k+1,2*w+1,w,k] vs [w,k]-sized arrays
%// need to introduce leading singletons with permute() in the latter
%// in order to have shape [1,1,w,k] compatible with the first array
ll = 1./sqrt(bsxfun(@minus,x2,permute(x1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2 ...
           + bsxfun(@minus,y2,permute(y1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2);
ll(isinf(ll)) = 0;

%// compute fft2, operating on [2*k+1,2*w+1,w,k]
%// will return fft2 for each index in the [w,k] subspace
nn = ifft2(fft2(g2).*fft2(ll));

%// we need nn(w+1,k+1,:,:) which is exactly of size [w,k] as needed
N = reshape(nn(w+1,k+1,:,:),[w,k]);  %// quicker than squeeze()
N = real(N);  %// this solution leaves an imaginary part of around 1e-12

czas=toc;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Matlab中更改矩阵中没有循环的值 - Change values in matrix without loops in Matlab 使用从X中的行到矩阵Y中的行的指针恢复矩阵X,而无需在MATLAB中执行循环 - Recover matrix X using pointers from rows in X to rows in matrix Y without doing loops in MATLAB MATLAB:如何在不使用for循环的情况下使用1-D矢量索引对多维矩阵进行子集化? - MATLAB: How to subset a multidimensional matrix using 1-D vector indices without for loops? 动态矩阵乘法无循环 - Dynamic matrix multiplication without loops 将一个索引到零矩阵中而没有循环 - Indexing ones into a matrix of zeros without loops 通过多列值w / o循环过滤矩阵(Matlab)? - Filter matrix by multiple column values w/o loops (Matlab)? Python 3D Arrays 中的时间序列计算不使用嵌套循环? - Python Time-Series Calculations in 3D Arrays without using Nested Loops? Matlab:数字数组索引到字符串数组(无循环) - Matlab: Numerical array index into a string array (without loops) 将矩阵的每一行中的三个元素相加-无循环 - Sum three elements in every row of the matrix - without loops 将矩阵列转换为对角矩阵并在没有 for 循环的情况下将它们包装起来 - Transform matrix columns into diagonal matrices and wrap them up without for loops
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM