优化从MATLAB矩阵中提取数据?

优化从MATLAB矩阵中提取数据?,matlab,matrix,Matlab,Matrix,给定n维值矩阵:通过任意索引(即坐标)检索值的最有效方法是什么 例如,在随机5x5矩阵中,如果我想要(1,1)(2,3)和(4,5)处的值,那么仅返回这些坐标处的值的最有效方法是什么 例如,如果我在一个单独的矩阵中提供这些坐标,是否有一行可以完成这项工作?比如: x=rand(5,5); y=[[1,1];[2,3];[4,5]]; z=x(y); 但那不起作用 但是有一个警告,由于各种原因,我无法使用线性索引-结果必须使用原始索引返回。这些矩阵的大小可能非常大,所

给定n维值矩阵:通过任意索引(即坐标)检索值的最有效方法是什么

例如,在随机5x5矩阵中,如果我想要(1,1)(2,3)和(4,5)处的值,那么仅返回这些坐标处的值的最有效方法是什么

例如,如果我在一个单独的矩阵中提供这些坐标,是否有一行可以完成这项工作?比如:

    x=rand(5,5);

    y=[[1,1];[2,3];[4,5]];

    z=x(y);
但那不起作用


但是有一个警告,由于各种原因,我无法使用线性索引-结果必须使用原始索引返回。这些矩阵的大小可能非常大,所以我也不想使用循环。

如果你反对使用线性索引和循环,唯一的替代方法,AFAIK,是逻辑索引。但是如果
y
总是以您建议的形式出现,则需要根据
y
中指定的索引创建一个逻辑矩阵

你能解释一下为什么不允许线性索引吗

无论如何,如果你想要一个非常愚蠢的答案(这是我能提供的全部信息):

z=diag(x(y(:,1),y(:,2))

当然,这将不必要地创建一个巨大的矩阵,并从中提取对角线元素(您需要的元素)——但它可以在一行中完成,等等

编辑:如果限制是对原始数据使用线性索引,则可以使用线性索引创建逻辑矩阵,并使用该矩阵索引
x
。例如

% Each element of L is only one byte
L = false(size(x)); 
% Create the logical mask
L(sub2ind(size(x),y(:,1),y(:,2))) = true;
% Extract the required elements
z = x(L);
类似地,对于三维矩阵:

x = rand(3,3,3);
y = [1 1 1;2 2 2;3 3 3];
L = false(size(x));
L(sub2ind(size(x),y(:,1),y(:,2),y(:,3))) = true;
z = x(L);

此外,逻辑索引应该比线性索引更快,因此除了构建掩码之外,您的状态也很好。

如果您反对使用线性索引和循环,那么唯一的替代方法AFAIK是逻辑索引。但是如果
y
总是以您建议的形式出现,则需要根据
y
中指定的索引创建一个逻辑矩阵

你能解释一下为什么不允许线性索引吗

无论如何,如果你想要一个非常愚蠢的答案(这是我能提供的全部信息):

z=diag(x(y(:,1),y(:,2))

当然,这将不必要地创建一个巨大的矩阵,并从中提取对角线元素(您需要的元素)——但它可以在一行中完成,等等

编辑:如果限制是对原始数据使用线性索引,则可以使用线性索引创建逻辑矩阵,并使用该矩阵索引
x
。例如

% Each element of L is only one byte
L = false(size(x)); 
% Create the logical mask
L(sub2ind(size(x),y(:,1),y(:,2))) = true;
% Extract the required elements
z = x(L);
类似地,对于三维矩阵:

x = rand(3,3,3);
y = [1 1 1;2 2 2;3 3 3];
L = false(size(x));
L(sub2ind(size(x),y(:,1),y(:,2),y(:,3))) = true;
z = x(L);

此外,逻辑索引应该比线性索引更快,因此除了构建掩码之外,您的状态也很好。

为什么sub2ind单独不适合这个问题?我不认为需要逻辑掩码;e、 g

z = x(sub2ind(size(x),y(:,1),y(:,2)))

应该也能工作。

为什么单独使用sub2ind不适合此问题?我不认为需要逻辑掩码;e、 g

z = x(sub2ind(size(x),y(:,1),y(:,2)))

应该也能用。

音乐停了很久才来参加聚会,但我还是忍不住

如果您需要“完全”索引,因为工具箱中有一个bug,并且工具箱一次只加载矩阵的一部分,您可以考虑跟随工具箱的行为。通过两件事可以获得大矩阵的大效率增益

1) 不要复制不需要复制的东西;例如,这包括创建一个与原始矩阵大小相同的逻辑数组(虽然它名义上是“有效的”,但每个元素需要一个字节。如果矩阵太大,无法一次装入内存,那么即使是1/8大小的矩阵也可能很重要)

2) 保持内存一致性:访问“同一区域”中的内存,或者发现自己由于大量磁盘交换而变慢;即使所有内容都放在内存中,保持“缓存一致性”也可以显著提高性能。如果可以按存储顺序访问矩阵元素,则速度会大大加快

为了解决第一点,您需要寻找一种不需要创建完整副本的方法(因此Jacob的答案是否定的)。为了解决第二个问题,您需要在访问矩阵之前对索引进行排序——这样,可以“从同一内存块”访问的任何元素都将被删除


这两种技术结合在下面。我假设numel(y)在音乐停止很久之后才来参加聚会,但我还是忍不住

如果您需要“完全”索引,因为工具箱中有一个bug,并且工具箱一次只加载矩阵的一部分,您可以考虑跟随工具箱的行为。通过两件事可以获得大矩阵的大效率增益

1) 不要复制不需要复制的东西;例如,这包括创建一个与原始矩阵大小相同的逻辑数组(虽然它名义上是“有效的”,但每个元素需要一个字节。如果矩阵太大,无法一次装入内存,那么即使是1/8大小的矩阵也可能很重要)

2) 保持内存一致性:访问“同一区域”中的内存,或者发现自己由于大量磁盘交换而变慢;即使所有内容都放在内存中,保持“缓存一致性”也可以显著提高性能。如果可以按存储顺序访问矩阵元素,则速度会大大加快

为了解决第一点,您需要寻找一种不需要创建完整副本的方法(因此Jacob的答案是否定的)。为了解决第二个问题,您需要在访问矩阵之前对索引进行排序——这样,可以“从同一内存块”访问的任何元素都将被删除

这两种技术结合在下面。我假设
numel(y)您的输出应该是什么
z = arrayfun(@(a,b)x(a,b),y(:,1),y(:,2));