我给出了一个指数列表,例如i = [3 5]和向量v = 1:6。我需要一个函数f,它返回给定索引i的向量v的逻辑映射,例如:
f(i, length(v)) = [0 0 1 0 1 0]由于我将调用这个函数数百万次,我想使它尽可能快。是否有执行此任务的内置函数?
发布于 2013-01-30 15:35:25
我知道我在游戏中迟到了,但我真的很想找到一个和ismember一样优雅的更快的解决方案。事实上,有一种方法使用了无文档的ismembc函数:
ismembc(v, i)基准测试
N = 7;
i = [3 5];
%// slayton's solution
tic
for ii = 1:1e5
clear idx;
idx(N) = false;
idx(i) = true;
end
toc
%// H.Muster's solution
tic
for ii = 1:1e5
v = 1:N;
idx = ismember(v, i);
end
toc
%// Jonas' solution
tic
for ii = 1:1e5
idx = sparse(i, 1, true, N, 1);
end
toc
%// ismembc solution
tic
for ii = 1:1e5
v = 1:N;
idx = ismembc(v, i);
end
toc我得到的是:
Elapsed time is 1.482971 seconds.
Elapsed time is 6.369626 seconds.
Elapsed time is 2.039481 seconds.
Elapsed time is 0.776234 seconds.令人惊讶的是,ismembc确实是最快的!
编辑:
对于非常大的N值(即当v是一个大数组时),更快的解决方案实际上是slayton的(以及HebeleHododo的)。你有相当多的策略可供选择,请仔细挑选:)
由H.Muster编辑:
以下是包括_ismemberoneoutput在内的基准测试结果
Slayton's solution:
Elapsed time is 1.075650 seconds.
ismember:
Elapsed time is 3.163412 seconds.
ismembc:
Elapsed time is 0.390953 seconds.
_ismemberoneoutput:
Elapsed time is 0.477098 seconds.有趣的是,Jonas的解决方案不适合我,因为我得到了一个Index exceeds matrix dimensions.错误.
由胡加蒙编辑:
值得注意的是,ismembc需要两个输入都是数值输入、排序输入、非稀疏输入和非NaN值,这是来源文件中很容易忽略的细节。
发布于 2013-01-30 14:58:48
只需创建一个逻辑索引向量,并将所需位置设置为true/false
idx = false( size( v) );
idx( i ) = true;这可以用如下所示的函数包装:
function idx = getLogicalIdx(size, i)
idx = false(size);
idx(i) = true;
end如果您需要一个大小相同的索引向量,用于分配该向量一次的一百万次操作,然后在每次迭代时对其进行操作:
idx = false(size(v)); % allocate the vector
while( keepGoing)
idx(i) = true; % set the desired values to true for this iteration
doSomethingWithIndecies(idx);
idx(i) = false; % set indices back to false for next iteration
end如果您真的需要性能,那么您可以编写一个mex函数来完成这一任务。下面是我编写的一个非常基本的、未经测试的函数,比其他方法快约2倍:
#include <math.h>
#include <matrix.h>
#include <mex.h>
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
double M;
double *in;
M = mxGetScalar(prhs[0]);
in = mxGetPr(prhs[1]);
size_t N = mxGetNumberOfElements(prhs[1]);
plhs[0] = mxCreateLogicalMatrix( M,1 );
mxLogical *out= mxGetLogicals( plhs[0] );
int i, ind;
for (i=0; i<N; i++){
out[ (int)in[i] ] = 1;
}
}在matlab中有几种不同的分配向量的方法。有些人比其他人更快,请参阅下面这篇无文档的Matlab文章,以获得一个很好的总结:
下面是比较不同方法的一些快速基准。最后一个方法是目前最快的,但它要求您对每个操作使用相同大小的逻辑索引向量。
N = 1000;
ITER = 1e5;
i = randi(5000,100,1);
sz = [N, 1];
fprintf('Create using false()\n');
tic;
for j = 1:ITER
clear idx;
idx = false( N, 1 );
idx(i) = true;
end
toc;
fprintf('Create using indexing\n');
tic;
for j = 1:ITER
clear idx;
idx(N) = false;
idx(i) = true;
end
toc;
fprintf('Create once, update as needed\n');
tic;
idx = false(N,1);
for j = 1:ITER
idx(i) = true;
idx(i) = false;
end
toc;
fprintf('Create using ismembc\n');
a = ones(N,1);
tic;
for j = 1:ITER
idx = ismembc(1:N, i);
end
toc;发布于 2013-01-30 15:08:20
您可以使用ismember
i = [3 5];
v = 1:6;
ismember(v,i)会回来
ans =
0 0 1 0 1 0对于可能更快的版本,您可以尝试
builtin('_ismemberoneoutput', v, i)请注意,我只对您指定的行向量进行了测试。
https://stackoverflow.com/questions/14606863
复制相似问题