混合型Matlab数据结构-what';s时间+;节省空间?

混合型Matlab数据结构-what';s时间+;节省空间?,matlab,performance,data-structures,large-data,bigdata,Matlab,Performance,Data Structures,Large Data,Bigdata,我需要处理大量混合类型的表格数据-字符串和双精度。我认为这是一个标准问题。在Matlab中,处理这个问题的最佳数据结构是什么 雷肯定不是答案。它的内存效率极低。(测试如下所示)。数据集(来自统计工具箱)在时间和空间上都非常低效。这就剩下structarray或structOfArray了。我在下面的四个不同选项中对时间和内存进行了测试,在我看来,数组结构是我测试的最佳选项 我对Matlab比较陌生,坦率地说,这有点令人失望。无论如何-寻找关于我是否遗漏了什么,或者我的测试是否准确/合理的建议。除

我需要处理大量混合类型的表格数据-字符串和双精度。我认为这是一个标准问题。在Matlab中,处理这个问题的最佳数据结构是什么

雷肯定不是答案。它的内存效率极低。(测试如下所示)。数据集(来自统计工具箱)在时间和空间上都非常低效。这就剩下structarray或structOfArray了。我在下面的四个不同选项中对时间和内存进行了测试,在我看来,数组结构是我测试的最佳选项

我对Matlab比较陌生,坦率地说,这有点令人失望。无论如何-寻找关于我是否遗漏了什么,或者我的测试是否准确/合理的建议。除了访问/转换/内存使用之外,我是否遗漏了其他考虑因素,这些考虑因素可能会随着我更多地使用这些东西编写代码而出现。(仅供参考,我正在使用R2010b)

**测试1:访问数据项的访问速度

cellarray:0.002s
dataset:36.665s       %<<< This is horrible
structarray:0.001s
struct of array:0.000s
==================代码:测试#1

===================代码:测试2


我想说的是,如果你需要管理大量的数据,那么MATLAB不是最好的选择。选择合适的数据库,并最终将所需的数据导入MATLAB

但是,如果您打算无论如何使用MATLAB,我仍然会选择字段名,也就是说,如果您不需要像结构中那样以字段名的形式对数据进行语法引用

使用光线时,请记住,每个单元格都会产生112字节的开销。因此,我将为每个列创建一个单元格(而不是为每个标量双精度创建一个单元格):

和内存方面(无时间变化):

此外,您所称的数组结构通常是用“标量”结构来表示的,而不是结构数组(或非标量结构)


如果我没有记错的话,当您开始嵌套字段时,结构的读/写性能往往会下降(不过我需要找到特定的线程)

使Matlab代码节省空间和时间的方法是使用大型原语数组,即double、int或char数组。这将使内存中的布局更紧凑,并允许您执行矢量化操作

对于表格数据,每一列的类型都是相同的,但是不同的列可能具有不同的类型,并且通常会有比列多得多的行。您经常会对一列的所有元素进行操作——比较或数学运算,或者对一列进行隐藏选择,这有助于进行矢量化操作。因此,将每一列存储为一个列数组,最好是一组基元。可以将这些列粘贴在结构的字段或单元向量的元素中;从性能角度看,这无关紧要,结构形式将更具可读性,看起来更像一个表。二维单元阵列或其他数据结构,如果将所有元素分解为自己的小MXArray,则不会执行accepatbly

也就是说,如果您有一个10000行×10列的表,那么您希望有一个10长的单元格数组或10字段结构,其中每个字段或元素都包含一个10000长的基本列向量

dataset
object对象基本上是一个围绕列数组结构的包装器,如前所述,它被固定在一个对象中。但是Matlab中的对象比常规结构和单元有更大的开销;每次访问它时,您都要为一个或多个方法调用付费。看一看(完全披露:这是我的答案之一)


您设置的测试并不能说明Matlab代码的性能如何,因为它是在进行标量单元素访问。也就是说,它为循环中每次通过的列元素和行元素访问付费。如果您的Matlab代码正在这样做,那么您已经不走运了。为了加快速度,您需要在循环外部弹出列—也就是说,将昂贵的列访问操作提升到外部循环或设置代码—然后执行向量化操作(如
+
==
,“虽然
数据集
确实很慢,但您的计时速度却非常慢。我在访问时获得
数据集:0.7s
,而其他的顺序与您的相同。我在32位WinXP+1上运行R2013a,这是一个很好的解释和深刻的答案。此外,OOP开销问题也确实提高了性能。”例如,在这个测试中(R2013a中),对于
dataset
访问,我只得到了0.7秒与OP报告的36秒相比,当然还有改进的余地。如果你能访问最新版本的银行,更新你的基准测试结果会很有趣。是的,升级听起来是个好主意。非OOP性能也应该提高。thoug担心其他人将不得不更新基准测试h-我换了工作,目前没有Matlab许可证。
Cellarray(doubles)->matrix:d->m: 0.865s
Cellarray(mixed)->structarray:c->sc: 0.268s
Cellarray(doubles)->structarray:d->sd: 0.430s
Cellarray(mixed)->struct of arrays:c->sac: 0.361s
Cellarray(doubles)->struct of arrays:d->sad: 0.887s
  Name           Size               Bytes  Class     Attributes
    c         100000x10            68000000  cell                
    d         100000x10            68000000  cell                
    m         100000x10             8000000  double              
    sac            1x1             38001240  struct              
    sad            1x1              8001240  struct              
    sc        100000x1             68000640  struct              
    sd        100000x1             68000640  struct  
  %% cellarray
  c = cell(100000,10);
  c(:,[1,3,5,7,9]) = num2cell(zeros(100000,5));
  c(:,[2,4,6,8,10]) = repmat( {'asdf'}, 100000, 5);
  cols = strcat('Var', strtrim(cellstr(num2str((1:10)'))))';
  te = tic;
  for iii=1:1000
      x = c(1234,5);
  end
  te = toc(te);
  fprintf('cellarray:%0.3fs\n', te);
  %% dataset
  ds = dataset( { c, cols{:} } );
  te = tic;
  for iii=1:1000
      x = ds(1234,5);
  end
  te = toc(te);
  fprintf('dataset:%0.3fs\n', te);
  %% structarray
  s = cell2struct( c, cols, 2 );
  te = tic;
  for iii=1:1000
      x = s(1234).Var5;
  end
  te = toc(te);
  fprintf('structarray:%0.3fs\n', te);
  %% struct of arrays
  for iii=1:numel(cols)
      if iii/2==floor(iii/2) % even => string
          sac.(cols{iii}) = c(:,iii);
      else
          sac.(cols{iii}) = cell2mat(c(:,iii));
      end
  end
  te = tic;
  for iii=1:1000
      x = sac.Var5(1234);
  end
  te = toc(te);
  fprintf('struct of array:%0.3fs\n', te);
%% cellarray
% c - cellarray containing mixed type 
c = cell(100000,10);
c(:,[1,3,5,7,9]) = num2cell(zeros(100000,5));
c(:,[2,4,6,8,10]) = repmat( {'asdf'}, 100000, 5);
cols = strcat('Var', strtrim(cellstr(num2str((1:10)'))))';
% c - cellarray containing doubles only
d = num2cell( zeros( 100000, 10 ) );
%% matrix
% doubles only
te = tic;
m = cell2mat(d);
te = toc(te);
fprintf('Cellarray(doubles)->matrix:d->m: %0.3fs\n', te);
%% structarray
% mixed
te = tic;
sc = cell2struct( c, cols, 2 );
te = toc(te);
fprintf('Cellarray(mixed)->structarray:c->sc: %0.3fs\n', te);
% doubles
te = tic;
sd = cell2struct( d, cols, 2 );
te = toc(te);
fprintf('Cellarray(doubles)->structarray:d->sd: %0.3fs\n', te);
%% struct of arrays
% mixed
te = tic;
for iii=1:numel(cols)
    if iii/2==floor(iii/2) % even => string
        sac.(cols{iii}) = c(:,iii);
    else
        sac.(cols{iii}) = cell2mat(c(:,iii));
    end
end
te = toc(te);
fprintf('Cellarray(mixed)->struct of arrays:c->sac: %0.3fs\n', te);
% doubles
te = tic;
for iii=1:numel(cols)
    sad.(cols{iii}) = cell2mat(d(:,iii));
end
te = toc(te);
fprintf('Cellarray(doubles)->struct of arrays:d->sad: %0.3fs\n', te);
%% 
clear iii cols te;
whos
c = cell(1,10);
c(1,1:2:10) = num2cell(rand(1e5,5),1);
c(1,2:2:10) = {cellstr(repmat('asdf', 100000, 1))};
Name           Size               Bytes  Class    Attributes
c              1x10            38000600  cell