【问题标题】:Trouble in Matlab Preallocating with a Complex For LoopMatlab 使用复杂的 For 循环预分配的问题
【发布时间】:2010-07-22 15:01:05
【问题描述】:

我对 matlab 还很陌生,但为了我的工作,我需要导入一个庞大的数据集并以某种方式组织它。我已经编写了一个可以做到这一点的代码,但是效率很低(这只是我的第三个主要代码,需要几个小时)。 Matlab 告诉我,我可以预先分配我的变量(实际上大约 50 次),但我无法看到如何做到这一点,因为我不确定对于 for 循环中的每次迭代,数据将被添加到哪个矩阵。代码本身可能比我更好地解释了这一点。
(这只是其中的一小部分,但希望能显示我的问题)

for x= 1:length(firstinSeq)
            for y= 1:length(littledataPassed-1)
                if firstinSeq(x,1)== littledataPassed(y,1) && firstinSeq(x,2)== littledataPassed(y,2) 
                        switch firstinSeq(x,3)
                            case 0
                                for z= 0:1000
                                    w= y+z;  
                                    if firstinSeq(x,4)== littledataPassed(w,4) 
                                        if littledataPassed(w,6)== 1 && firstinSeq(x,2)== littledataPassed(w,2) && littledataPassed(w,5)== 0 
                                            msgLength0= [msgLength0; firstinSeq(x,:) littledataPassed(w,:)];
                                            break
                                        else continue
                                        end
                                    else msgLength0= [msgLength0; firstinSeq(x,:) [0 0 0 0 0 0]];  
                                        break
                                    end
                                end
                            case 1
                                for z= 0:1000
                                    w= y+z; 
                                    if firstinSeq(x,4)== littledataPassed(w,4) %if sequence not the same, terminate
                                        if littledataPassed(w,6)== 1 && firstinSeq(x,2)== littledataPassed(w,2) && littledataPassed(w,5)== 0
                                            msgLength1= [msgLength1; firstinSeq(x,:) littledataPassed(w,:)];
                                            break
                                        else continue
                                        end
                                    else msgLength1= [msgLength1; firstinSeq(x,:) [0 0 1 0 0 0]]; 
                                        break        
                                    end
                                end
                            case 2
                                for z= 0:1000
                                    w= y+z;
                                    if firstinSeq(x,4)== littledataPassed(w,4)
                                        if littledataPassed(w,6)== 1 && firstinSeq(x,2)== littledataPassed(w,2) && littledataPassed(w,5)== 0
                                            msgLength2= [msgLength2; firstinSeq(x,:) littledataPassed(w,:)];
                                            break
                                        else continue
                                        end
                                    else msgLength2= [msgLength2; firstinSeq(x,:) [0 0 2 0 0 0]];
                                        break
                                    end
                                end
                                for z= 0:1000
                                    w= y+z;
                                    if firstinSeq(x,4)== littledataPassed(w,4)
                                        if littledataPassed(w,6)== 1 && firstinSeq(x,2)== littledataPassed(w,2) && littledataPassed(w,5)== 1
                                            msgLength2= [msgLength2; firstinSeq(x,:) littledataPassed(w,:)];
                                            break
                                        else continue
                                        end
                                    else msgLength2= [msgLength2; firstinSeq(x,:) [0 0 2 0 1 0]];  
                                        break
                                    end
                                end

关于如何预分配这些变量(msgLength0、1、2 等)的任何想法?他们没有为循环中的每个值添加数据,我不确定每次运行的最终大小。我的switch目前一共有8个case,导致这个程序很慢。

【问题讨论】:

    标签: matlab


    【解决方案1】:

    如果我正确阅读了您的代码,那么变量msgLengthN 会在每次通过最内层循环时扩展?如果是这样,这会提示您可能需要预先分配一个名为 msgLengthAll 的数组并在执行过程中填充该数组,确保每个条目中都有一个值来区分 0、1、2 等。

    如果您事先不知道要为msgLengthAll 分配多少空间,那么您可以:

    • 扫描输入文件一次以确定这个和其他数组需要多大。多次读取大文件来处理它们并没有什么可耻的,它可能会为您节省大量时间。或
    • 沉迷于一些花哨的分配方案,首先您猜测msgLengthAll 需要多少空间,然后当它满时分配更多内存。有多种方法可以决定在每个扩展点分配多少:固定大小或可能与已经分配的一样多(即每次扩展时分配双倍)。当然,这可能相当复杂。

    您是否正在逐行读取文件并随时更新内存中的变量?还是您正在阅读整个文件,然后在内存中整理内容? ENORMOUS 有多大?你有多少内存?

    【讨论】:

    • 感谢您的回复。它是一个研究项目的完整数据集。大约 30,000 行的 210 个文本文件和大约 80,000 行的 210 个文本文件(它们成对出现)被读取到 Matlab 中。我尝试设置脚本的方式是读取一对文件,匹配相应的数据行,然后在我想要处理的行上运行这个荒谬的循环。此循环处理约 200,000 行数据(firstinSeq 变量)。所以回答你的问题,导入,然后排序。我会为你发布我的整个脚本,但它的效率低得令人尴尬,需要 600 行。
    • @Maxwell:因此,如果您采用一对匹配的文件,一个文件中的 30,000 行是否匹配 1:~3 与另一个中的 80,000 行?然后您是否尝试在 Matlab 中构建一个数组来存储两者的聚合数据?对于这种数据整理,我通常会在开始尝试将数据读入 Matlab 之前尽可能多地使用诸如 sed 和 awk 之类的实用程序,如果没有其他原因的话,以提高性能。
    • 好吧,自从第一次发布以来,我一直在玩这个代码,并对其进行了大量修改。我终于想出了如何预分配这个。代码仍然很慢,因为我真的不知道如何简化/矢量化这个循环,但改进了很多。
    • @Mark:是的。数据是关于消息的;较小的文件只是较大文件中消息的子集,但包含不同的信息,因此需要匹配它们。以我想要的方式获取数据是相当有效的(只需 5 分钟即可匹配、排序、分隔重要的行。)仍然很慢的代码部分是循环(部分发布在上面。)我已经预先分配,但是在那里你有什么其他方法可以让这更快而不会有太多麻烦吗? (我在矢量化方面很糟糕,这很令人沮丧,因为我知道我可能会以某种方式在这里做到)
    【解决方案2】:

    您可以通过在 1000 个元素块中找到符合您的标准的记录索引,然后一举将它们附加到 msgLength0,从而对每个 switch case 中的处理进行矢量化。以下是case 0代码的矢量化版本:

    indexStop = find(firstinSeq(x,4) != littledataPassed(y:y+1000,4), 1, 'first');
    if isempty(indexStop)
       indexStop = 1000;
    end
    indexProcess = find(littledataPassed(y:y+indexStop,6) == 1 & ...
       littledataPassed(y:y+indexStop,2) == firstinSeq(x,2) & ...
       littledataPassed(y:y+indexStop,5) == 0);
    msgLength0 = [msgLength0; firstinSeq(x,:) littledataPassed(y+indexProcess-1,:); [0 0 0 0 0 0]];
    

    对外部循环进行矢量化也可以大大减少执行时间。我对您的数据知之甚少,无法建议一种特定方法,但也许使用 reshape 和/或 repmat 函数来创建可以在矢量上操作的数组可能是路要走。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      • 2016-09-07
      相关资源
      最近更新 更多