Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Matlab整数字符串解码。。。速度优化_String_Matlab_Performance - Fatal编程技术网

String Matlab整数字符串解码。。。速度优化

String Matlab整数字符串解码。。。速度优化,string,matlab,performance,String,Matlab,Performance,我有以下问题: 我需要通过以下关联将整数序列“c”解码为字符字符串消息“m”: numpos = 10 % ( = size(c,2)/2) c = [3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3] “c”的每一行表示2*numpos整数,其中第一个numpos参数编码了 types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'} 第二个numpos参数仅在类型包含如下字符“@”时应用: m = ' c:1@6 d:1@10

我有以下问题:

我需要通过以下关联将整数序列“c”解码为字符字符串消息“m”:

  numpos = 10 % ( = size(c,2)/2)
  c = [3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3]
“c”的每一行表示2*numpos整数,其中第一个numpos参数编码了

types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'} 
第二个numpos参数仅在类型包含如下字符“@”时应用:

  m = ' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6' 
我目前的解决办法如下:

  function m = c2m(c,types)

  numpos = size(c,2)/2;

  F = cellfun(@(f) [' ' f], strrep(types,'@',':%d@'),'unif',0);
  m = arrayfun(@(f,k) sprintf(f{1},k),F(c(:,1:numpos)),c(:,numpos+(1:numpos)),'unif', 0);
  m = arrayfun(@(i) horzcat(m{i,:}), (1:numlines)', 'unif', 0)

  end
  numlines = 10;
  c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
  types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

  m = c2m(c,types);

  m =

    10×1 cell array

      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
测试代码如下:

  function m = c2m(c,types)

  numpos = size(c,2)/2;

  F = cellfun(@(f) [' ' f], strrep(types,'@',':%d@'),'unif',0);
  m = arrayfun(@(f,k) sprintf(f{1},k),F(c(:,1:numpos)),c(:,numpos+(1:numpos)),'unif', 0);
  m = arrayfun(@(i) horzcat(m{i,:}), (1:numlines)', 'unif', 0)

  end
  numlines = 10;
  c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
  types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

  m = c2m(c,types);

  m =

    10×1 cell array

      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
代码对我来说仍然太慢,我正在寻找任何加速。在这种情况下,CPU时间的大部分都花在内置函数“sprintf”上

问题的典型现实规模如下:

   numpos ~ 30 ... 60
   numlines ~ 1e4 ... 1e5

有什么想法吗?

这里有一个想法可以开始尝试

numpos = 10 % ( = size(c,2)/2)
c = [3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3];
types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'} 
然后

m= 1×10单元阵列 第1列至第10列

{'c:1@6'}{'d:1@10“}{a:1@0“}{a:1@0'}{'d:2@10{b:2@2“}{e:2@11{b:3@2{c:3@6{c:3@6“}


以下是
c2m
功能的替代方案,对于上面列出的
numpos
numlines
的典型范围,该功能的速度要快2到3倍:

function m = c2m(c, types)
  numpos = size(c, 2)/2;
  [pre, post] = strtok(types(c(:, 1:numpos)), '@');
  mid = strsplit(sprintf(' :%i', 1:max(max(c(:, numpos+1:2*numpos)))));
  mid = mid(c(:, numpos+1:2*numpos).*~cellfun(@isempty, post)+1);
  m = cellstr(char(join(strcat(pre, mid, post))));
end
首先,使用在
'@'
处拆分
c
的前半部分。然后创建一个单元格数组
mid
,其中包含字符串
{''':1':2'…':N'}
,其中
N
c
后半部分的最大值。这允许我们通过简单地索引到
mid
来获得我们想要的字符串,从而避免将昂贵的转换函数应用于整个矩阵(如、、等)。索引正好是
c
的右半部分乘以表示
'@'
是否存在的逻辑数组(使用获取),然后递增1

最后,将三个不同的字符串(
pre
mid
post
)连接在一起,按行收集到字符串,使用(自R2016b起出现),然后转换为包含和的字符数组的单元格数组

使用以下值对其进行测试:

numpos = 10;
numlines = 10;
c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3], numlines, 1);
types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};
我们得到了预期的结果:

m =

  10×1 cell array

    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'

在16b中,MATLAB提供了一些新的文本函数,使这变得简单。同样在16b中,MATLAB提供了新的字符串数据类型,这使得它变得非常快速

 function m = c2m_new(c,types, numlines)

     types = string(types);

     num_values = size(c,2)/2;

     a = c(:,1:num_values);
     b = c(:,(num_values+1):end);

     m = types(a);
     m = insertBefore(m,"@", ":" + b);
     m = join(m,2);
 end

>> numlines = 10;
>> c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
>> types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};
>> c2m_new(c,types,numlines)

ans = 

  10×1 string array

    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
从绩效来看:

>> numlines = 1E4;
>> c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
>> types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

% My solution
>> tic; for i = 1:10; c2m_new(c,types, numlines); end; toc
Elapsed time is 0.669311 seconds.

% michalkvasnicka's solution
>> tic; for i = 1:10; c2m(c,types, numlines); end; toc
Elapsed time is 23.643991 seconds.

% gnovice's solution
>> tic; for i = 1:10; c2m_gnovice(c,types, numlines); end; toc
Elapsed time is 8.960392 seconds.

您可以中断输入以获得更大的灵活性。我想到了
split(type,'@')
,也想到了分离
c
。这样您就可以在一个命令行中连接所有的部分信息。@marsei您能更具体一点,直接用代码向我显示您的建议吗?在
types={a@0' 'b@2' 'c@6' 'd@10' 'e@11'};'
这样您就可以拆分字符串(您将在进程结束时使用
strep
删除它。然后类似于
strcat(类型左,repmat(':',10,1),c(11:20),repmat('@',10,1))
。不确定它是否更快,但你可以用这个方法预先分配。@marsei我仍然不明白你到底给我什么建议!你能在这篇文章中直接修改我的代码+需要修改输入数据来告诉我你的想法吗?但是,“@”在我的代码中起着非常特殊的作用。通常不是所有类型都包含“@”!!!谢谢您的帮助,但是您的代码比我的代码慢得多。因为numlines=1e4是CPUmycode=1.8秒,CPUyourcode=2.8秒。@michalkvasnicka:我使用了一种新方法进行了更新。您现在应该看到显著的加速。在代码中出现严重错误的情况下,您是如何测量加速的?错误使用。*整数只能是com与同一类的整数或标量双精度组合。c2m mid=mid中的错误(c(:,numpos+1:2*numpos)。*double(~cellfun(@isempty,post))+1);@michalkvasnicka:只有将
c
初始化为整数类型时才会出现该错误。我将其初始化为双精度,就像在示例数据中一样。恐怕我已将c初始化为双精度(默认情况下)!!??