17

我正在使用单元格来管理我正在处理的某些内容中的数据。我希望能够执行以下操作:

A = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
B = cellfun( @(X)( randn( 5,5 ) ), cell( 5,1 ), 'UniformOutput', 0 );
%#
%# Each of the following would fail if cell member dimensions
%# don't match up
%#
%# matrix sums for each cell entry
%# C = A + B;
C = cellfun( @(X,Y)( X + Y ), A, B, 'UniformOutput', 0 );
%#
%# direct/hadamard product
%# D = A .* B;
D = cellfun( @(X,Y)( X .* Y ), A, B, 'UniformOutput', 0 );
%#
%# matrix-matrix products (not across all entries)
%# E = A * B;
E = cellfun( @(X,Y)( X * Y ), A, B, 'UniformOutput', 0 );

但是,我不希望使用极其冗长的语法来做到这一点。当我想要做的只是为单元格上的数学运算符提供定义时,为此创建一个新类似乎有点过分。

问题是:上课是唯一的方法吗?

如果我编写一个类来执行此操作,它肯定会使编写代码更容易。我看到的最大的负面影响与优化有关,尽管还有一些其他的事情让我对此感到烦恼..

在幕后进行的任何优化(例如,当 Jacket 编译某些东西以在 GPU 上运行时)可能会更难确定要进行哪些优化。例如,假设我有两个单元格 (A,B),其中包含许多适当维度的矩阵。如果我编写代码来生成一个新单元格:

Z = c1*A + c2*B

...使用标量 {c1,c2},我可以这样编写它,使夹克(或其他)可以轻松确定它应该进行以下计算:

Z{kk} = c1*A{kk} + c2*B{kk}

或者比这更好的优化。否则。它最终可能会导致速度变慢和/或内存效率降低,例如:

temp1 = cellfun( @(X)( c1*X ), A );
temp2 = cellfun( @(X)( c2*X ), B );
Z     = cellfun( @plus, temp1, temp2 );

假设 MATLAB 或 Jacket 无法对其进行优化,这最终会占用过多的内存。

4

1 回答 1

25

事实上,可以为 MATLAB 中的内置数据类型创建新的运算符或重载现有的运算符。我在对另一个关于修改整数类型的默认溢出行为的SO 问题的回答中描述了一个示例。

首先,您可能想查看当前存在哪些用于元胞数组的方法。您可以使用函数METHODS来做到这一点,这就是我在 MATLAB R2010b 中得到的:

>> methods cell

Methods for class cell:

aa2nt            issorted         regexptranslate  strfind          
accumarray       newdepfun        reshape          strjust          
cell2struct      nt2aa            rna2dna          strmatch         
ctranspose       nwalign          seq2regexp       strtok           
display          permute          setdiff          transpose        
dna2rna          regexp           setxor           union            
intersect        regexpi          sort             unique           
ismember         regexprep        strcat           

算术运算符方法将在上面的列表中显示为它们的等效函数,例如plus运算+符或运算times.*。仅为元胞数组定义了transpose方法(运算符)。.'您必须自己创建其余部分,定义给定运算符对元胞数组参数的行为方式。

您可以通过首先创建一个名为的新文件夹@cell并将其放在MATLAB 路径上的现有文件夹中来做到这一点。然后,您将把新方法放在@cell文件夹中。例如,元胞数组方法的一个非常简单的实现plus(没有任何输入检查、错误检查等)将是:

function C = plus(A,B)
  C = cellfun(@plus,A,B,'UniformOutput',false);  %# Apply plus cell-wise
end

在上面的代码中,您可能首先要检查操作数AB是相同大小的元胞数组。但是,您可以创建任何您想要的独特功能,例如允许B成为一个标量值,该值将添加到A. 完全由您来定义+运算符对元胞数组的行为方式。

这将允许您以更紧凑的方式编写代码,如下例所示:

>> A = {[1 2 3] [4 5] 6};  %# One 3-element cell array
>> B = {5 [4 5] 2};        %# Another 3-element cell array
>> C = A+B;                %# Use the new plus operator
>> C{:}                    %# Display the cell contents

ans =

     6     7     8

ans =

     8    10

ans =

     8

我无法真正谈论幕后优化以及这可能会如何影响它们。我知道文档“提高性能的技术”特别提到了有关重载内置函数的内容:

在任何标准 MATLAB 数据类上重载 MATLAB 内置函数都会对性能产生负面影响。例如,如果您重载plus函数以不同方式处理任何整数类,您可能会阻碍 MATLAB 内置函数代码中的某些优化plus,从而可能会减慢使用此重载的任何程序。

但是,在您的情况下,您不会重载类的现有函数。您只是在创建该课程不存在的新课程,因此很难说这最终会对性能产生什么影响。

于 2011-03-21T04:13:36.667 回答