向量化代码-如何减少MATLAB计算时间

在秋天的冲浪者

我有这段代码

N=10^4;
for i = 1:N
    [E,X,T] = fffun(); % Stochastic simulation. Returns every time three different vectors (whose length is 10^3).
    X_(i,:)=X;
    T_(i,:)=T;
    GRID=[GRID T];
end
GRID=unique(GRID);
% Second part
for i=1:N
for j=1:(kmax)
    f=find(GRID==T_(i,j) | GRID==T_(i,j+1));
    s=f(1);
    e=f(2)-1;

 counter(X_(i,j), s:e)=counter(X_(i,j), s:e)+1;
end
end

该代码对随机过程进行N次不同的模拟(由10 ^ 3个事件组成,这些事件在离散时刻(T向量)发生,具体取决于特定的模拟。现在,我想知道(第二部分)与时间有关的函数,在特定状态下有多少个模拟(X的取值范围是1到10),我的想法是:创建一个网格矢量,其中包含所有模拟中发生的所有时刻。发生某事的时间步长,并递增与该特定时间段相对应的所有计数器的增量。

但是,第二部分非常繁重(我的意思是在标准四核CPU上要花费几天的时间)。而且不应该。是否有任何想法(也许是关于更有效地比较向量的想法)来减少CPU时间?

这是一个独立的“ second_part”

N=5000;
counter=zeros(11,length(GRID));

for i=1:N
    disp(['Counting sim #' num2str(i)]);
    for j=1:(kmax)
        f=find(GRID==T_(i,j) | GRID==T_(i,j+1),2);
        s=f(1);
        e=f(2)-1;

        counter(X_(i,j), s:e)=counter(X_(i,j), s:e)+1;

    end
end

counter=counter/N;
stop=find(GRID==Tmin);
stop=stop-1;
plot(counter(:,(stop-500):stop)')

以及相关的伪数据(filedropper.com/data_38)。在实际情况下,矩阵有2x行和10x列。

EBH

这是我的理解:

T_是来自N个模拟的时间步长矩阵。
X_T_这些仿真中的仿真状态矩阵

因此,如果您这样做:

[ut,~,ic]= unique(T_(:));

您将获得ic,它是中所有唯一元素的索引向量T_然后,您可以编写:

counter = accumarray([ic X_(:)],1);

并得到counter没有。行数作为您唯一的时间步长,没有。列中的唯一状态X_(均为且必须为整数)。现在您可以说,对于每个时间步ut(k),仿真处于状态的时间mcounter(k,m)

在您的数据,唯一的组合mk具有大于1的值是(1,1)


编辑:

从下面的评论中,我了解到您记录了所有状态更改以及发生状态更改的时间步长。然后,每次模拟更改状态时,您都希望从所有模拟中收集所有状态,并计算每种类型有多少个状态。

这里的主要问题是您的时间是连续的,因此基本上每个元素T_都是唯一的,并且您有超过一百万个时间步长要循环。完全矢量化此过程将需要大约80GB的内存,这可能会卡住您的计算机。

因此,我在时间步长中寻求矢量化和循环的结合。我们首先找到所有唯一的时间间隔,然后预先分配counter

ut = unique(T_(:));
stt = 11; % no. of states
counter = zeros(stt,numel(ut));r = 1:size(T_,1);
r = 1:size(T_,1); % we will need that also later

然后,我们遍历中的所有元素ut,并且每次T_都以矢量化的方式在所有模拟中寻找相关的时间步长最后我们histcounts用来计算所有状态:

for k = 1:numel(ut)
    temp = T_<=ut(k); % mark all time steps before ut(k)
    s = cumsum(temp,2); % count the columns
    col_ind = s(:,end); % fins the column index for each simulation
    % convert the coulmns to linear indices:
    linind = sub2ind(size(T_),r,col_ind.');
    % count the states:
    counter(:,k) = histcounts(X_(linind),1:stt+1);
end

在我的计算机上进行1000次仿真大约需要4秒钟,因此整个过程增加了一个多小时的时间。不太快...

您还可以尝试以下一项或两项调整,以进一步压缩运行时间:

  1. 正如您在这里所读到的accumarray似乎在较小的数组中工作得更快histcouns所以可能要切换到它。

  2. 另外,直接计算线性索引比更快sub2ind,因此您可能需要尝试一下。

在上面的循环中实现这些建议,我们得到:

R = size(T_,1);
r = (1:R).';
for k = 1:K
    temp = T_<=ut(k); % mark all time steps before ut(k)
    s = cumsum(temp,2); % count the columns
    col_ind = s(:,end); % fins the column index for each simulation
    % convert the coulmns to linear indices:
    linind = R*(col_ind-1)+r;
    % count the states:
    counter(:,k) = accumarray(X_(linind),1,[stt 1]);
end

在我的计算机上,切换到accumarray或删除sub2ind的效果有所改善,但是并不一致(timeit用于测试中的100或1K元素ut),因此您最好自己进行测试。但是,这仍然很长。


您可能要考虑的一件事是尝试离散化您的时间步长,因此循环使用的独特元素要少得多。在您的数据中,大约有8%的时间间隔小于1。如果您可以假设该时间间隔短到可以视为一个时间步长,则可以四舍五入T_并获得约12.5K个唯一元素,这大约需要一个分钟即可结束。您可以以0.1个间隔(小于时间间隔的1%)执行相同操作,并获得122K元素进行循环,这大约需要8个小时...

当然,以上所有时序都是使用相同算法的粗略估计。如果你选择圆的时间可能有更好的方法来解决这个问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在MATLAB中向量化代码

来自分类Dev

如何向量化此代码?

来自分类Dev

如何使用 mvnpdf 向量化 Matlab 代码?

来自分类Dev

向量化倍频程/ matlab代码

来自分类Dev

在 Matlab 中使用 xor 向量化代码

来自分类Dev

如何向量化以下python代码?

来自分类Dev

如何“向量化”此重复的C ++代码?

来自分类Dev

有什么办法可以向量化这个Matlab代码吗?

来自分类Dev

将向量化的Matlab代码传输到python,numpy

来自分类Dev

有什么办法可以向量化这个Matlab代码吗?

来自分类Dev

我如何向量化以下python代码(图像过渡)?

来自分类Dev

如何在R中向量化此代码

来自分类Dev

如何以向量化形式编写此numpy代码?

来自分类Dev

如何使用for循环在r中向量化我的代码?

来自分类Dev

你能减少这个 matlab 代码的计算时间吗?

来自分类Dev

向量化-Matlab

来自分类Dev

向量化MATLAB循环

来自分类Dev

如何向量化?

来自分类Dev

如何向量化功能?

来自分类Dev

如何向量化LSTM?

来自分类Dev

如何向量化功能

来自分类Dev

MATLAB向量化:计算邻域矩阵

来自分类Dev

MATLAB向量化:计算邻域矩阵

来自分类Dev

如何向量化此python代码以使其更高效?(速度)

来自分类Dev

如何使用SSE4.1 pminuq / pminud / etc操作码让gcc向量化代码?

来自分类Dev

如何向量化此python代码以使其更高效?(速度)

来自分类Dev

如何避免循环以减少此代码的计算时间?

来自分类Dev

向量化回归图计算

来自分类Dev

log(n!) 的向量化计算