向量化 for 循环以填充行
Vectorize a for loop to fill row
我试图向量化以下内容:
for i = 2:n
mat = NaN(m,i);
for j = 1:m
mat(j,:) = getVal(i);
end
num(i) = max(mat(:));
end
进入
for i = 2:n
mat = NaN(m,i);
j = 1:m;
mat(j,:) = getVal(i);
num(i) = max(mat(:));
end
但是,MATLAB 给我一个错误:"Subscripted assignment dimension mismatch"我不确定我的代码哪里出错了?
此外,是否可以向量化整个嵌套 for 循环,而不仅仅是内部循环?
谢谢!
编辑: 抱歉,函数 getVal()
returns 大小为 'i' 的随机向量。这用于在提供的代码中填充矩阵的行,因此这个 post 的问题标题 "Vectorize a for loop to fill row"。抱歉,如果不清楚。
示例数据:
对于 i = 2,输出如下:
Matrix Output 1 矩阵的行在内循环中一次填充一行。
对于 i = 3,它与上面相同,而是 3 列:
Matrix Output 2
希望已经清楚了吗?
编辑 2: 我刚刚按照 Cris Luengo 的解决方案的建议尝试使用 repmat
。这是我的输出:Matrix Output with repmat。我需要函数 getVal 每次都是 运行,而不是简单地 运行 一次并将其内容复制到行中。
编辑 3: 好的,这是我的函数 getVal(i):
function [A] = getVal(m)
X = normrnd(0,1,[m,m]);
A = triu(X) + triu(X)';
A = A - diag(diag(A))/2;
A = eig(A)';
end
根据您的示例,getVal(i) 不会为重复调用它而不断返回相同的输出。由于我没有您的代码,因此我使用以下方法模拟了该行为:
function out = getVal(i)
out = rand(1, i);
end
现在,如果您无法触及 getVal 但希望对所有内容进行矢量化,我会使用 arrayfun
(https://www.mathworks.com/help/matlab/ref/arrayfun.html)
mat = cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)); % UniformOutput is needed because output isn't a scalar. Cell2mat is used to convert to the same matrix as previously.
您的其余代码是相同的。请注意,一切都像以前一样工作,只是没有循环。
但是你还有外循环。另一个 arrayfun 处理:
num = arrayfun(@(i, m) max(max(cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)))), 1:n, repmat(m, 1, n));
请注意,这不会计算 mat
,但我认为它并不是真正需要的,因为它会不断为每个 i
.
重写
但是...它并不快。我用 n=1000,m=1000 计时,你的 2 循环代码给了我 7.3s,第一个矢量化方法在 10.8s 中完成,最后一个在 10.7s 中完成,2 循环方法再次在 7.1 中结束这次是。
真正加速代码的明显步骤是对 getVal 进行矢量化 - 我无法帮助您,只要我不知道它到底做了什么。但是,如果这种上兰德方法在大约 5 秒内完成,如果它 returns 一步完成整个垫子。
我试图向量化以下内容:
for i = 2:n
mat = NaN(m,i);
for j = 1:m
mat(j,:) = getVal(i);
end
num(i) = max(mat(:));
end
进入
for i = 2:n
mat = NaN(m,i);
j = 1:m;
mat(j,:) = getVal(i);
num(i) = max(mat(:));
end
但是,MATLAB 给我一个错误:"Subscripted assignment dimension mismatch"我不确定我的代码哪里出错了?
此外,是否可以向量化整个嵌套 for 循环,而不仅仅是内部循环?
谢谢!
编辑: 抱歉,函数 getVal()
returns 大小为 'i' 的随机向量。这用于在提供的代码中填充矩阵的行,因此这个 post 的问题标题 "Vectorize a for loop to fill row"。抱歉,如果不清楚。
示例数据: 对于 i = 2,输出如下: Matrix Output 1 矩阵的行在内循环中一次填充一行。 对于 i = 3,它与上面相同,而是 3 列: Matrix Output 2
希望已经清楚了吗?
编辑 2: 我刚刚按照 Cris Luengo 的解决方案的建议尝试使用 repmat
。这是我的输出:Matrix Output with repmat。我需要函数 getVal 每次都是 运行,而不是简单地 运行 一次并将其内容复制到行中。
编辑 3: 好的,这是我的函数 getVal(i):
function [A] = getVal(m)
X = normrnd(0,1,[m,m]);
A = triu(X) + triu(X)';
A = A - diag(diag(A))/2;
A = eig(A)';
end
根据您的示例,getVal(i) 不会为重复调用它而不断返回相同的输出。由于我没有您的代码,因此我使用以下方法模拟了该行为:
function out = getVal(i)
out = rand(1, i);
end
现在,如果您无法触及 getVal 但希望对所有内容进行矢量化,我会使用 arrayfun
(https://www.mathworks.com/help/matlab/ref/arrayfun.html)
mat = cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)); % UniformOutput is needed because output isn't a scalar. Cell2mat is used to convert to the same matrix as previously.
您的其余代码是相同的。请注意,一切都像以前一样工作,只是没有循环。
但是你还有外循环。另一个 arrayfun 处理:
num = arrayfun(@(i, m) max(max(cell2mat(arrayfun(@getVal, repmat(i, m, 1), 'UniformOutput', false)))), 1:n, repmat(m, 1, n));
请注意,这不会计算 mat
,但我认为它并不是真正需要的,因为它会不断为每个 i
.
但是...它并不快。我用 n=1000,m=1000 计时,你的 2 循环代码给了我 7.3s,第一个矢量化方法在 10.8s 中完成,最后一个在 10.7s 中完成,2 循环方法再次在 7.1 中结束这次是。
真正加速代码的明显步骤是对 getVal 进行矢量化 - 我无法帮助您,只要我不知道它到底做了什么。但是,如果这种上兰德方法在大约 5 秒内完成,如果它 returns 一步完成整个垫子。