学习笔记:MapReduce on Ray

本文介绍了MapReduce的基本概念和工作原理,并展示了如何使用Ray这一分布式执行框架实现MapReduce。通过实例展示了在Ray上执行Map和Reduce操作,以求解列表的平方和,同时讨论了Ray的安装和基本用法。此外,还探讨了Ray在分布式计算中的优势和在实际问题中的应用。
摘要由CSDN通过智能技术生成

目录

本文主要介绍:

  • MapReduce
    • 什么是MapReduce
    • Map & Reduce
  • Ray
    • 什么是Ray
    • Ray的一些简单用法
  • MapReduce on Ray
    • 简单用法
    • 实战
  • Reference

本文实验环境及相关材料:

/*
理论上支持其他平台,只要Python的版本和Ray的版本对应即可。笔者已在macOS和Ubuntu上面进行测试,均无错误。如果读者在实现的过程中发现错误,欢迎提issue.
本文中的代码已上传至Github,文中在抄写代码的过程中可能出现纰漏,代码以Github为准。欢迎大家指正,谢谢!
*/

MapReduce

什么是MapReduce?

MapReduce最早(~2004年)是由Jeff Dean等人提出的一种面向大规模数据处理的并行计算模型和方法。源于函数式编程语言中的map和reduce内置函数,MapReduce的主要思想是Map(映射)和Reduce(规约),通常用于大规模数据集的并行运算。

关于MapReduce的原理和例子网络上有挺多优秀的文章,本文只是简单说一下MapReduce的原理和一个粗糙的例子,以便读者快速理解。个人建议可以去翻翻MapReduce的论文和相关的资料(见文末)。

Map(映射):

Map过程就是把一组数据按照某种Map映射成新的数据。如下面这个例子,就是用Python3.6中内置的map函数,将list[0, 1, 2, 3, 4]中的每个元素进行了平方的操作。(需要注意的是,Python3.x中的map返回的是迭代器,2.x返回的是列表)

# Python2.x 中map方法返回的是列表
# Python3.x 中map方法返回的是迭代器
iter_map = map(lambda x: x ** 2, range(5))
for item in item_map:
    print(item, end=" ")
# >> Output: 0 1 4 9 16 

Reduce(规约):

Reduce过程就是把map输出的结果汇总到一起。继上面的例子,我们计算了几个数的平方,现在需要求他们的和。reduce方法需要传入两个参数,然后递归地对每个参数(除第一个参数)执行运算

# Python2.x 中可以直接调用reduce
# Python3.x 中将reduce放到functools里面了
from functools import reduce
iter_map = map(lambda x: x ** 2, range(5))  # 0 1 4 9 16
reduce(lambda: x, y: x + y, iter_map)  # 0+1+4+9+16 = 30
# >> Output: 30

例子:

Hadoop中的一个例子,用MapReduce实现的词频统计:

(图源于网络) MapReduce on Hadoop

假设现在要统计Wikipedia上所有文章的词频,单机是放不下了。一个简单的思路就是将文章分批(Splitting),每个机器分别处理一批数据(Mapping),最后再将数据汇总(Reducing)。在汇总之前,需要将相同的单词放在一起(Shuffling),以便汇总。

在本文中,我们只关心Mapping和Reducing步骤的实现。

Ray

什么是Ray?

“Ray is a flexible, high-performance distributed execution framework.”

Ray是由UC Berkeley的RISELab (Real­Time Intelligence with Secure Execution) 提出的一种新型的分布式执行框架。RISELab前身是AMPLab,AMPLab (Algorithms, Machines and People Lab) 主导研发了Spark等在大数据领域著名的项目。从RISE的名字可以知道,实验室目前侧重于安全的、实时的智能系统。

Ray即如此,其主要是为深度学习、增强学习和分布式训练等量身定做,并能做到实时计算(尤其是在增强学习领域,如自动驾驶,人们会更加关注性能表现)。按照目前的发展趋势来看,Ray的出现是很有必要。

有兴趣的读者可以看看《UC Berkeley提出新型分布式执行框架Ray》,和知乎上的问题《如何看UCBerkeley RISELab即将问世的Ray,replacement of Spark?》中的高赞回答。网上可搜到,文末也会给出。两篇资料都分析得挺到位,在此不再复述了。读者如果感兴趣的话也可以读读Ray的论文,当然以后如果时间允许的话我也会写一篇关于Ray的paper reading.

安装Ray很简单:

pip install ray

如果你使用的是Anaconda,注意目前无法通过conda来安装。当然,你也可以通过源码安装/Docker等方式来安装。

在每次使用Ray之前,需要执行 ray.init() 来初始化Ray:

import ray
ray.init()
""" Output: 
Process STDOUT and STDERR is being redirected to /tmp/ray/session_2018-12-22_17-15-29_3097/logs.
Waiting for redis server at 127.0.0.1:52922 to respond...
Waiting for redis server at 127.0.0.1:50403 to respond...
Starting the Plasma object store with 6.714851328 GB memory using /dev/shm.

======================================================================
View the web UI at http://localhost:8890/notebooks/ray_ui.ipynb?token=d187db1e2b1d612be2336a469836843fa6d7e9a15fba3564
======================================================================
"""

调用ray.init()之后,我们可以看到Ray启动了Redis server, 如果只是使用单机版本的Ray的话,可以暂不关心Redis server的地址等信息,只知道它初始化成功即可。

关于ray.init()的主要启动参数:

  • redis_address: (str) – 要连接的Redis server的地址,不填则默认在本地启动。(程序退出时会关掉Redis server)
  • num_cpus: (int) – 本地调度器配置的cpu数量
  • ignore_reinit_error: (bool) – 如果第二次调用ray.init,程序会报错并退出,设为True可不抛出异常
    具体解析和API文档请移步至: The Ray API - Ray 0.6.0 documentation

Ray的简单使用:

在Ray中,分别通过ray.put()ray.get()方法来设置和读取变量的值。其中,ray.put() 方法返回的是对象的id, ray.get() 方法需要传入对象的id,返回变量的值。如:

x = "Hello Ray"
x_id = ray.put(x)
# 当然,ray.put()的传入参数也可以是number, list...等其他类型,如:
#    x_id = ray.put([i for i in range(10)])
print(x_id)
# >> Output: ObjectID(ffffffffba55fc8d16f249d14868946b44ff9652)

x_r
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值