【发布时间】:2014-09-29 13:18:07
【问题描述】:
假设我有以下 9 x 5 矩阵:
myArray = [
54.7 8.1 81.7 55.0 22.5
29.6 92.9 79.4 62.2 17.0
74.4 77.5 64.4 58.7 22.7
18.8 48.6 37.8 20.7 43.5
68.6 43.5 81.1 30.1 31.1
18.3 44.6 53.2 47.0 92.3
36.8 30.6 35.0 23.0 43.0
62.5 50.8 93.9 84.4 18.4
78.0 51.0 87.5 19.4 90.4
];
我有这个矩阵的 11 个“子集”,我需要在每个子集上运行一个函数(比如说max)。可以使用以下逻辑矩阵来识别子集(按列识别,而不是按行识别):
myLogicals = logical([
0 1 0 1 1
1 1 0 1 1
1 1 0 0 0
0 1 0 1 1
1 0 1 1 1
1 1 1 1 0
0 1 1 0 1
1 1 0 0 1
1 1 0 0 1
]);
或通过线性索引:
starts = [2 5 8 10 15 23 28 31 37 40 43]; #%index start of each subset
ends = [3 6 9 13 18 25 29 33 38 41 45]; #%index end of each subset
这样第一个子集是 2:3,第二个是 5:6,依此类推。
我可以找到每个子集的max,并将其存储在一个向量中,如下所示:
finalAnswers = NaN(11,1);
for n=1:length(starts) #%i.e. 1 through the number of subsets
finalAnswers(n) = max(myArray(starts(n):ends(n)));
end
循环运行后,finalAnswers 包含每个数据子集的最大值:
74.4 68.6 78.0 92.9 51.0 81.1 62.2 47.0 22.5 43.5 90.4
不使用for 循环是否可以获得相同的结果?换句话说,这段代码可以向量化吗?这种方法会比目前的方法更有效吗?
编辑: 我对建议的解决方案进行了一些测试。我使用的数据是一个 1,510 x 2,185 矩阵,其中包含 10,103 个子集,长度从 2 到 916 不等,子集长度的标准差为 101.92。
我将每个解决方案都包装在 tic;for k=1:1000 [code here] end; toc; 中,结果如下:
-
for循环方法 ---Elapsed time is 16.237400 seconds. - Shai的方法---
Elapsed time is 153.707076 seconds. - 丹的方法---
Elapsed time is 44.774121 seconds. - Divakar 的方法 #2 ---
Elapsed time is 127.621515 seconds.
注意事项:
- 我还尝试通过将
k=1:1000 for循环包裹在accumarray行周围来对 Dan 的方法进行基准测试(因为其余的可能是 理论上只运行一次)。在这种情况下,时间是 28.29 秒。 - 对 Shai 的方法进行基准测试,同时保留
lb = ...行k循环的时间为 113.48 秒。 - 当我运行 Divakar 的代码时,
bsxfun行出现Non-singleton dimensions of the two input arrays must match each other.错误。 我通过使用共轭转置(撇号trade_starts(1:starts_extent)上的操作员') 和intv(1:starts_extent)在调用bsxfun的代码行中。我是 不知道为什么会发生这个错误...
我不确定我的基准测试设置是否正确,但似乎for 循环在这种情况下实际上运行得最快。
【问题讨论】:
-
在您的代码中,您是否有机会从
starts和ends创建myLogicals,还是像starts和ends一样存在? /跨度> -
另外,您可以使用 GPU 吗?当使用
gpuArrays移植到 GPU 时,矢量化非常适合。 -
@Divakar 问题 1:我先创建
myLogicals,然后从中获取starts和ends。问题2:我确实可以使用相对强大的GPU(680 GTX),但我对gpuArrays完全不熟悉。你碰巧有一个很好的在线资源链接,我可以在那里了解更多信息吗?这听起来很有趣 -
让我问你一件事 - 你说你正在创建
"10,103 subsets that varied in length from 2 to 916 with a standard deviation of subset length of 101.92"。这是您的实际数据,还是您只是为了对解决方案进行基准测试。当您处理同质数据的大数据块时,矢量化会产生良好的结果,但标准偏差值如此之高 -101.92,它不适合矢量化技术,因此 for 循环始终是最佳解决方案。 -
关于我的解决方案中的错误,您不需要在其中进行任何更改,但错误可能是因为您的数据设置方式。我假设
starts和ends对数据进行了排序,并且两个子集之间不能有任何重叠。这些标准是否得到维护?
标签: matlab vectorization