【发布时间】:2015-05-27 22:05:27
【问题描述】:
我有一个带有 Python UDF 的 Pig 脚本,它应该生成用户级功能。我的数据由 Pig 预处理,然后作为元组列表发送到 UDF。 UDF 将处理数据元组并为每个用户返回一个带有我的功能计算机的字符数组。发生这种情况的代码如下所示:
-- ... loading data above
data = FOREACH data_raw GENERATE user_id, ...; -- some other metrics as well
-- Group by ids
grouped_ids = GROUP data BY user_id PARALLEL 20;
-- Limit the ids to process
userids = LIMIT grouped_ids (long)'$limit';
-- Generate features
user_features = FOREACH userids {
GENERATE group as user_id:chararray,
udfs.extract_features(data) as features:chararray;
}
UDF 代码显然是在 reducer 中运行的,并且由于某种原因,它总是跑到一个 reducer 中,这需要相当长的时间。我正在寻找一种方法来并行执行它,因为现在我的工作总共需要 22 分钟,其中 18 分钟在这个单一的减速器中。
Pig 通常会尝试将 1GB 的数据分配给 reducer,而我的数据确实不到 1GB,大约 300-700MB,但在 UDF 端相当耗时,所以这显然不是最优的,而我的其余部分集群是空的。
我尝试过的事情:
- 设置
default parallel会影响整个脚本脚本,但仍无法使具有 UDF 的 reducer 并行化 - 在
GROUP data BY user_id上手动设置parallel会并行化组的输出并调用多个reducer,但在UDF 启动时,它又是一个reducer - 设置
pig.exec.reducers.bytes.per.reducer允许您为每个reducer 设置例如最多10MB 的数据,它显然适用于我脚本的其他部分(并且破坏了并行性,因为这也会影响我管道开始时的数据准备- 正如预期的那样)但同样不允许多个减速器与此 UDF 一起运行。
据我了解发生了什么,我不明白为什么 - 如果 shuffle 阶段可以将 user_id 散列到一个或多个减速器 - 为什么这个脚本不能产生多个减速器,在那里实例化 UDF并根据 user_id 将对应的数据散列到正确的 reducer。我的数据或任何东西都没有明显的偏差。
我显然在这里遗漏了一些东西,但看不到什么。有没有人有任何解释和/或建议?
编辑:我更新了代码,因为缺少一些重要的东西:我在GROUP BY 和FOREACH 之间运行LIMIT。我还清理了不相关的信息。为了便于阅读,我还将内联代码扩展为单独的行。
【问题讨论】:
标签: mapreduce apache-pig user-defined-functions