Main Content

mapreduce

用于分析无法载入内存的数据集的编程方法

说明

示例

outds = mapreduce(ds,mapfun,reducefun) 将 map 函数 mapfun 应用于输入数据存储 ds,然后将与每个唯一键关联的值传递到 reduce 函数 reducefun。输出数据存储是一个 KeyValueDatastore 对象,该对象指向当前文件夹中的 .mat 文件。

可以使用 outds = mapreduce(ds,mapfun,reducefun,mr)mapreduce 指定运行时配置设置。mr 输入是调用 mapreducer 函数的结果。通常,此参量用于 Parallel Computing Toolbox™、MATLAB® Parallel Server™MATLAB Compiler™。有关详细信息,请参阅Speed Up and Deploy MapReduce Using Other Products

outds = mapreduce(___,Name,Value) 支持任何上述语法,且可使用一个或多个 Name,Value 对组参量指定其他选项。例如,可以指定 'OutputFolder',后跟指定输出文件夹的路径的字符向量。

示例

全部折叠

使用 mapreduce 来统计数据集中每个唯一航空公司的航班数量。

使用 airlinesmall.csv 数据集创建一个数据存储。这一 12 MB 的数据集包含多个航空公司的 29 列航班信息,包括到港和离港时间。在此示例中,选择 UniqueCarrier(航空公司名称)作为感兴趣的变量。指定 'TreatAsMissing' 名称-值对组,以便数据存储将 'NA' 值视为缺失,并指定 'MissingValue' 名称-值对组以用零替换缺失值。

ds = tabularTextDatastore('airlinesmall.csv','TreatAsMissing','NA',...
    'MissingValue',0);
ds.SelectedVariableNames = 'UniqueCarrier';
ds.SelectedFormats = '%C';

预览数据。

preview(ds)
ans=8×1 table
    UniqueCarrier
    _____________

         PS      
         PS      
         PS      
         PS      
         PS      
         PS      
         PS      
         PS      

对数据运行 mapreduce。map 和 reduce 函数统计每个数据块中每个航空公司名称的实例数,然后将这些中间计数合并为最终计数。此方法利用由 mapreduce 执行的使用唯一键作为排序依据的中间排序。函数 countMappercountReducer 包含在此脚本的结尾。

outds = mapreduce(ds, @countMapper, @countReducer);
********************************
*      MAPREDUCE PROGRESS      *
********************************
Map   0% Reduce   0%
Map  16% Reduce   0%
Map  32% Reduce   0%
Map  48% Reduce   0%
Map  65% Reduce   0%
Map  81% Reduce   0%
Map  97% Reduce   0%
Map 100% Reduce   0%
Map 100% Reduce  10%
Map 100% Reduce  21%
Map 100% Reduce  31%
Map 100% Reduce  41%
Map 100% Reduce  52%
Map 100% Reduce  62%
Map 100% Reduce  72%
Map 100% Reduce  83%
Map 100% Reduce  93%
Map 100% Reduce 100%
readall(outds)
ans=29×2 table
       Key          Value  
    __________    _________

    {'AA'    }    {[14930]}
    {'AS'    }    {[ 2910]}
    {'CO'    }    {[ 8138]}
    {'DL'    }    {[16578]}
    {'EA'    }    {[  920]}
    {'HP'    }    {[ 3660]}
    {'ML (1)'}    {[   69]}
    {'NW'    }    {[10349]}
    {'PA (1)'}    {[  318]}
    {'PI'    }    {[  871]}
    {'PS'    }    {[   83]}
    {'TW'    }    {[ 3805]}
    {'UA'    }    {[13286]}
    {'US'    }    {[13997]}
    {'WN'    }    {[15931]}
    {'AQ'    }    {[  154]}
      ⋮

map 函数 countMapper 利用数据是分类数据这一事实。对每个输入数据块使用 countcatscategories 函数来生成航空公司名称和相关计数的键/值对组。

function countMapper(data, info, intermKV)
% Counts unique airline carrier names in each block.
a = data.UniqueCarrier;
c = num2cell(countcats(a));
keys = categories(a);
addmulti(intermKV, keys, c)
end

reduce 函数 countReducer 读取由 map 函数生成的中间数据,并将所有计数相加以得出每个航空公司的单个最终计数。

function countReducer(key, intermValIter, outKV)
% Combines counts from all blocks to produce final counts.
count = 0;
while hasnext(intermValIter)
    data = getnext(intermValIter);
    count = count + data;
end
add(outKV, key, count)
end

输入参数

全部折叠

输入数据存储,指定为数据存储对象。使用 datastore 函数根据您的数据集创建数据存储对象。

mapreduce 仅适用于确定性数据存储。也就是说,如果对数据存储使用 read,使用 reset 重置数据存储,然后再次读取该数据存储,则这两种读取方式返回的数据必须相同。涉及非确定性数据存储的 mapreduce 计算会产生不可预测的结果。有关详细信息,请参阅Select Datastore for File Format or Application

map 函数的函数句柄。mapfun 从输入数据存储 ds 接收数据块,然后使用 addaddmulti 函数将键-值对组添加到中间的 KeyValueStore 对象中。mapreduce 对 map 函数的调用次数等于 datastore 中的数据块数目(数据块数目由数据存储的 ReadSize 属性确定)。

map 函数的输入是 datainfointermKVStoremapreduce 自动创建它们并将它们传递到 map 函数:

  • datainfo 输入是调用 datastoreread 函数的结果,mapreduce 在每次调用 map 函数之前自动执行该函数。

  • intermKVStoreKeyValueStore 中间对象的名称,map 函数需要使用该名称添加键-值对组。如果对 map 函数的任何调用都不会将键-值对组添加到 intermKVStore,则 mapreduce 不会调用 reduce 函数并且输出数据存储为空。

map 函数的模板示例为

function myMapper(data, info, intermKVStore)
%do a calculation with the data block
add(intermKVStore, key, value)
end

示例: @myMapper

数据类型: function_handle

reduce 函数的函数句柄。mapreduce 对 map 函数添加到中间的 KeyValueStore 的每个唯一键调用一次 reducefun。在每个调用中,mapreduce 将与活动键相关的值作为 ValueIterator 对象传递给 reducefunreducefun 函数使用 hasnextgetnext 函数循环显示每个键的值。然后,执行一些计算之后,它将键-值对组写入到最终输出中。

reduce 函数的输入是 intermKeyintermValIteroutKVStoremapreduce 自动创建它们并将它们传递到 reduce 函数:

  • intermKey 是来自中间的 KeyValueStore 对象的活动键。mapreduce 每次对 reduce 函数的调用都会根据中间 KeyValueStore 对象中的键指定一个新的唯一键。

  • intermValIter 是与活动键 intermKey 相关的 ValueIterator。这个 ValueIterator 对象包含与活动键相关的所有值。使用 hasnextgetnext 函数滚动这些值。

  • outKVStore 是最终 KeyValueStore 对象名称,reduce 函数需要使用该名称添加键-值对组。mapreduceoutKVStore 中获取输出键-值对组并在输出数据存储 outds 中返回它们,默认情况下是一个 KeyValueDatastore 对象。如果对 reduce 函数的任何调用都不会将键-值对组添加到 outKVStore,则输出数据存储为空。

Reduce 函数的模板示例为

function myReducer(intermKey, intermValIter, outKVStore)
while hasnext(intermValIter)
    X = getnext(intermValIter);
    %do a calculation with the current value, X
end
add(outKVStore, key, value)
end

示例: @myReducer

数据类型: function_handle

执行环境,指定为 MapReducer 对象。mr 是对 mapreducer 函数调用的结果。默认的 mr 参量是对 gcmr 的调用,它使用 mapreduce(在 MATLAB 中,默认值为 mapreducer(0),后者返回 SerialMapReducer 对象)的默认全局执行环境。

注意

此设置指定 mapreduce 的执行环境,无需在本地计算机上运行 mapreduce。有关详细信息,请参阅Speed Up and Deploy MapReduce Using Other Products

名称-值参数

将可选的参量对组指定为 Name1=Value1,...,NameN=ValueN,其中 Name 是参量名称,Value 是对应的值。名称-值参量必须出现在其他参量之后,但参量对组的顺序无关紧要。

在 R2021a 之前,使用逗号分隔每个名称和值,并用引号将 Name 引起来。

示例: outds = mapreduce(ds, @mapfun, @reducefun, 'Display', 'off', 'OutputFolder', 'C:\Users\username\Desktop')

数据存储输出类型,指定为 'Binary''TabularText''Binary' 的默认设置返回 KeyValueDatastore 输出数据存储,该存储指向输出文件夹中的二进制(.mat.seq)文件。'TabularText' 选项返回 tabularTextDatastore 输出数据存储,该存储指向输出文件夹中的 .txt 文件。

下表提供了每个输出类型的详细信息。

'OutputType'数据存储输出类型数据存储指向的文件类型Reduce 函数可添加的值Reduce 函数可添加的键详细信息
'Binary'(默认值)KeyValueDatastore.mat(或者针对 Hadoop® 运行时为 .seq)。任何有效的 MATLAB 对象。不含 NaN 值、复数值、逻辑值或稀疏值的字符向量、字符串或数值标量。不适用
'TabularText'TabularTextDatastore.txt不含 NaN 值、复数值、逻辑值或稀疏值的字符向量、字符串或数值标量。不含 NaN 值、复数值、逻辑值或稀疏值的字符向量、字符串或数值标量。
  • 文件采用 UTF-8 编码。

  • 键和值用制表符 (\t) 分隔开。

  • 行分隔符在 Windows® 上是 \r\n,在 Linux®Mac 上是 \n

数据类型: char | string

mapreduce 输出的目标文件夹,指定为文件路径。默认的输出文件夹是当前文件夹 pwd。可以通过完全限定路径或相对于当前文件夹的路径指定不同路径。

示例: mapreduce(..., 'OutputFolder', 'MyOutputFolder\Results') 为该输出指定相对于当前文件夹的文件路径。

数据类型: char | string

命令行进度输出的切换,指定为 'on''off'。默认值为 'on',这样在执行过程的 map 和 reduce 阶段 mapreduce 可以将进度信息显示在命令行窗口中。

数据类型: char | string

输出参量

全部折叠

输出数据存储,以 KeyValueDatastoreTabularTextDatastore 对象的形式返回。默认情况下,outds 是指向当前文件夹中的 .mat 文件的 KeyValueDatastore 对象。对 'OutputType''OutputFolder' 使用 Name,Value 对组参量,以便返回 tabularTextDatastore 对象或分别更改输出文件的位置。

mapreduce 不对 outds 中的键-值对组进行分类。它们的顺序在使用 mapreduce 的其他乘积时可能不同。

要查看 outds 的内容,请使用 datastorepreviewreadreadall 函数。

提示

  • 调试您的 mapreduce 算法以检查键-值对组如何通过不同的阶段,这很有用。要检查数据的移动,请在 map 和 reduce 函数中设置断点。mapreduce 的断点停止执行,使您能够检查相关变量的当前状态,例如 KeyValueStoreValueIterator。有关详细信息,请参阅Debug MapReduce Algorithms

  • 一些可在任意平台上优化 mapreduce 性能的建议有:

    • 最大限度减少对 map 函数的调用次数。最简单的方法是增大输入数据存储的 ReadSize 属性的值。这样,mapreduce 将较大的数据块传递到 map 函数,降低读取次数,减少数据存储。

    • 减少在 map 和 reduce 函数间发送的中间数据量。一种方法是使用 map 函数内的 unique 来组合相似键。请参阅Compute Mean by Group Using MapReduce中有关此方法的示例。

扩展功能

版本历史记录

在 R2014b 中推出