如何在matlab中对天线阵列因子表达进行矢量化

时间:2015-04-06 10:37:57

标签: arrays matlab signal-processing vectorization telecommunication

我在这里有天线阵列因子表达式:

Antenna Array factor

我已将数组因子表达式编码如下:

lambda = 1;
M = 100;N = 200; %an M x N array
dx = 0.3*lambda; %inter-element spacing in x direction
m = 1:M; 
xm = (m - 0.5*(M+1))*dx; %element positions in x direction

dy = 0.4*lambda;
n = 1:N;
yn = (n - 0.5*(N+1))*dy;

thetaCount = 360; % no of theta values

thetaRes = 2*pi/thetaCount; % theta resolution

thetas = 0:thetaRes:2*pi-thetaRes; % theta values

phiCount = 180;

phiRes = pi/phiCount;

phis = -pi/2:phiRes:pi/2-phiRes;

cmpWeights = rand(N,M); %complex Weights

AF = zeros(phiCount,thetaCount); %Array factor

tic
for i = 1:phiCount
    for j = 1:thetaCount

        for p = 1:M
            for q = 1:N

                AF(i,j) = AF(i,j) + cmpWeights(q,p)*exp((2*pi*1j/lambda)*(xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i))));

            end
        end
    end
end

如何对代码进行矢量化以计算阵列因子(AF)。

我想要一行:

AF(i,j) = AF(i,j) + cmpWeights(q,p)*exp((2*pi*1j/lambda)*(xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i))));

以矢量化形式编写(通过修改for循环)。

2 个答案:

答案 0 :(得分:1)

方法#1:全油门

最里面的嵌套循环会在每次迭代中生成此内容 - cmpWeights(q,p)*exp((2*pi*1j/lambda)*(xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i)))) ,这些迭代将在AF中为我们提供最终输出。

我们将 exp(.... 部分称为B。现在,B基本上有两部分,一部分是标量 (2*pi*1j/lambda) ,另一部分是标量 (xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i))) 由依赖的变量组成 原始循环版本中使用的四个迭代器 - i,j,p,q 。我们将其他部分称为C,以便日后参考。

让我们把所有这些都放到透视中:

  • Loopy版本的 AF(i,j) = AF(i,j) + cmpWeights(q,p)*exp((2*pi*1j/lambda)*(xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i)))) ,现在相当于AF(i,j) = AF(i,j) + cmpWeights(q,p)*B,其中 B = exp((2*pi*1j/lambda)*(xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i))))

  • B可以简化为 B = exp((2*pi*1j/lambda)* C) ,其中 C = (xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i)))

  • C取决于迭代器 - i,j,p,q

因此,在移植到矢量化的方式之后,它最终将成为这个 -

%// 1) Define vectors corresponding to iterators used in the loopy version
I = 1:phiCount;
J = 1:thetaCount;
P = 1:M;
Q = 1:N;

%// 2) Create vectorized version of C using all four vector iterators
mult1 = bsxfun(@times,sin(thetas(J)),cos(phis(I)).'); %//'
mult2 = bsxfun(@times,sin(thetas(J)),sin(phis(I)).'); %//'

mult1_xm = bsxfun(@times,mult1(:),permute(xm,[1 3 2]));
mult2_yn = bsxfun(@times,mult2(:),yn);
C_vect = bsxfun(@plus,mult1_xm,mult2_yn);

%// 3) Create vectorized version of B using vectorized C
B_vect = reshape(exp((2*pi*1j/lambda)*C_vect),phiCount*thetaCount,[]);

%// 4) Final output as matrix multiplication between vectorized versions of B and C
AF_vect = reshape(B_vect*cmpWeights(:),phiCount,thetaCount);

方法#2:内存不足

第二种方法会减少内存流量,并使用指数的分配属性 - exp(A+B) = exp(A)*exp(B)

现在,最初的循环版本就是这个 -

AF(i,j) = AF(i,j) + cmpWeights(q,p)*exp((2*pi*1j/lambda)*...
    (xm(p)*sin(thetas(j))*cos(phis(i)) + yn(q)*sin(thetas(j))*sin(phis(i))))

因此,在使用分配属性之后,我们最终会得到类似的东西 -

K = (2*pi*1j/lambda)
part1 = K*xm(p)*sin(thetas(j))*cos(phis(i));
part2 = K*yn(q)*sin(thetas(j))*sin(phis(i));
AF(i,j) = AF(i,j) + cmpWeights(q,p)*exp(part1)*exp(part2);

因此,相关的矢量化方法将变成这样的 -

%// 1) Define vectors corresponding to iterators used in the loopy version
I = 1:phiCount;
J = 1:thetaCount;
P = 1:M;
Q = 1:N;

%// 2) Define the constant used at the start of EXP() call
K = (2*pi*1j/lambda);

%// 3) Perform the sine-cosine operations part1 & part2 in vectorized manners
mult1 = K*bsxfun(@times,sin(thetas(J)),cos(phis(I)).'); %//'
mult2 = K*bsxfun(@times,sin(thetas(J)),sin(phis(I)).'); %//'

%// Perform exp(part1) & exp(part2) in vectorized manners
part1_vect = exp(bsxfun(@times,mult1(:),xm));
part2_vect = exp(bsxfun(@times,mult2(:),yn));

%// Perform multiplications with cmpWeights for final output
AF = reshape(sum((part1_vect*cmpWeights.').*part2_vect,2),phiCount,[])

快速基准测试

以下是原始循环方法问题中列出的输入数据的运行时和建议的方法#2 -

---------------------------- With Original Approach
Elapsed time is 358.081507 seconds.

---------------------------- With Proposed Approach #2
Elapsed time is 0.405038 seconds.

运行时表明 Approach #2 会带来惊人的性能提升!

答案 1 :(得分:1)

基本技巧是弄清楚什么是不变的,以及什么东西取决于下标术语 - 因此是矩阵术语。

总和:

  • C(n,m)是一个矩阵
  • 2π/λ是一个常数
  • sin(θ)cos(φ)是一个常数
  • x(m)y(n)是向量

所以我要做的两件事是:

  1. 使用xm
  2. ymmeshgrid()扩展为矩阵
  3. 把所有常数项都放在循环之外。
  4. 像这样:

    ...
    
    piFactor = 2 * pi * 1j / lambda;
    
    [xgrid, ygrid] = meshgrid(xm, ym);                                       % xgrid and ygrid will be size (N, M)
    
    for i = 1:phiCount
        for j = 1:thetaCount
    
            xFactor = sin(thetas(j)) * cos(phis(i));
            yFactor = sin(thetas(j)) * sin(phis(i));
    
            expFactor = exp(piFactor * (xgrid * xFactor + ygrid * yFactor)); % expFactor is size (N, M)
    
            elements = cmpWeights .* expFactor;                              % elements of sum, size (N, M)
    
            AF(i, j) = AF(i, j) + sum(elements(:));                          % sum and then integrate.
    
        end
    end
    

    你也许可以弄清楚如何矢量化外环,但希望这能为你提供一个起点。