惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
LINUX DO - 热门话题
S
Secure Thoughts
TaoSecurity Blog
TaoSecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threat Research - Cisco Blogs
AI
AI
B
Blog RSS Feed
S
Schneier on Security
雷峰网
雷峰网
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Cloudbric
Cloudbric
L
LINUX DO - 最新话题
罗磊的独立博客
有赞技术团队
有赞技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
博客园 - Franky
Attack and Defense Labs
Attack and Defense Labs
The Cloudflare Blog
Webroot Blog
Webroot Blog
Last Week in AI
Last Week in AI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 叶小钗
美团技术团队
L
Lohrmann on Cybersecurity
T
The Blog of Author Tim Ferriss
The Last Watchdog
The Last Watchdog
T
Troy Hunt's Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
Know Your Adversary
Know Your Adversary
O
OpenAI News
博客园 - 【当耐特】
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
Cybersecurity and Infrastructure Security Agency CISA
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
I
InfoQ
GbyAI
GbyAI
T
Threatpost
C
Cisco Blogs

元视角

.NET 生态下的 Agent 框架选型:从 ReAct 到原生推理 - 元视角 从「能用」到「好用」:LLM 流式响应实现方式的探索之路 - 元视角 当我用 2000 条聊天记录,让 AI 为我画一幅自画像 - 元视角 基于 Supabase 的 AI 应用开发探索 - 元视角 微博 × MCP:社交媒体新玩法解锁 - 元视角 四点钟海棠花未眠 - 元视角 Semantic Kernel × MCP:智能体的上下文增强探索 - 元视角 基于 K-Means 聚类分析实现人脸照片的快速分类 - 元视角 容器技术驱动下的代码沙箱实践与思考 - 元视角 温故而知新:后端通用查询方案的再思考 - 元视角 浅议 CancellationToken 在前后端协同取消场景中的应用 - 元视角 Semantic Kernel 视角下的 Text2SQL 实践与思考 - 元视角 关于 ChatGPT 的流式传输,你需要知道的一切 - 元视角 RAG 的是与非、Rewrite 和 Rerank - 元视角 使用 EFCore 和 PostgreSQL 实现向量存储及检索 - 元视角 基于 LLaMA 和 LangChain 实践本地 AI 知识库 - 元视角 使用 llama.cpp 在本地部署 AI 大模型的一次尝试 - 元视角 如何为 Git 配置多个 SSH Key - 元视角 C# 使用 LibUsbDotNet 实现 USB 设备检测 - 元视角 基于 C# 实现样式与数据分离的打印方案 - 元视角 基于 SVG 的图形交互方案实践 - 元视角 前端视频播放技术概览 - 元视角 温故而知新,再话 Python 动态导入 - 元视角 后 GPT 时代,NLP 不存在了? - 元视角 视频是不能 P 的系列:使用 Milvus 实现海量人脸快速检索 - 元视角 GDI+下字体大小自适应方案初探 - 元视角 小爱音箱集成 ChatGPT 的不完全教程 - 元视角 程序员视角下的三体世界随想 - 元视角 关于 Docker 容器配置信息的渐进式思考 - 元视角 在 Docker 容器内集成 Crontab 定时任务 - 元视角 为你的服务器集成 LDAP 认证 - 元视角 似花还似非花 - 元视角 视频是不能 P 的系列:使用 Dlib 实现人脸识别 - 元视角 浅议分布式链路追踪与日志的整合 - 元视角 关于 Git 大文件上传这件小事 - 元视角 .NET 进程内队列 Channel 的入门与应用 - 元视角 使用 Fody 实现 .NET 的静态编织 - 元视角 .NET Core + ELK 搭建可视化日志分析平台(下) - 元视角 聊一聊前端图片懒加载背后的故事 - 元视角 支持外部链接跳转的 Vue Router 扩展实现 - 元视角 视频是不能 P 的系列:OpenCV 和 Dlib 实现表情包 - 元视角 不得不说的 ASP.NET Core 集成测试 - 元视角 再议 DDD 视角下的 EFCore 与 领域事件 - 元视角 Vue.js 前端项目容器化部署实践极简教程 - 元视角 再见,人间四月天 - 元视角 Python 图像风格化迁移助力画家梦想 - 元视角 利用 ASP.NET Core 中的标头传播实现分布式链路追踪 - 元视角 利用 gRPC 实现文件的上传与下载 - 元视角 七种武器:延迟队列的原理和实现总结 - 元视角 gRPC 流式传输极简入门指南 - 元视角 Envoy 集成 Jaeger 实现分布式链路追踪 - 元视角 浅议非典型 Web 应用场景下的身份认证 - 元视角 gRPC 借助 Any 类型实现接口的泛化调用 - 元视角 分布式丛林探险系列之 Redis 集群模式 - 元视角 分布式丛林探险系列之 Redis 主从复制模式 - 元视角 通过 Python 预测 2021 年双十一交易额 - 元视角 gRPC 搭配 Swagger 实现微服务文档化 - 元视角 SSL/TLS 加密传输与数字证书的前世今生 - 元视角 使用 Python 自动识别防疫健康码 - 元视角 你不可不知的容器编排进阶技巧 - 元视角 ASP.NET Core 搭载 Envoy 实现 gRPC 服务代理 - 元视角 再话 AOP,从简化缓存操作说起 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务身份认证(JWT) - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的监控预警 - 元视角 ASP.NET Core 搭载 Envoy 实现微服务的反向代理 - 元视角 ASP.NET Core gRPC 打通前端世界的尝试 - 元视角 EFCore 实体命名约定库:EFCore.NamingConventions - 元视角 ASP.NET Core gRPC 集成 Polly 实现优雅重试 - 元视角 ASP.NET Core gRPC 健康检查的探索与实现 - 元视角 ASP.NET Core gRPC 拦截器的使用技巧分享 - 元视角 SnowNLP 使用自定义语料进行模型训练 - 元视角 使用 HttpMessageHandler 实现 HttpClient 请求管道自定义 - 元视角 ABP vNext 的实体与服务扩展技巧分享 - 元视角 ABP vNext 对接 Ant Design Vue 实现分页查询 - 元视角 源代码探案系列之 .NET Core 跨域中间件 CORS - 元视角 源代码探案系列之 .NET Core 限流中间件 AspNetCoreRateLimit - 元视角 源代码探案系列之 .NET Core 并发限制中间件 ConcurrencyLimiter - 元视角 通过 EmbededFileProvider 实现 Blazor 的静态文件访问 - 元视角 低代码,想说爱你不容易 - 元视角 记一次失败的 ThoughtWorks 面试经历 - 元视角 从 C# 1.0 到 C# 9.0,历代 C# 语言特性一览 - 元视角 通过 Python 分析 2020 年全年微博热搜数据 - 元视角 基于 Python 和 Selenium 实现 CSDN 一键三连自动化 - 元视角 使用多线程为你的 Python 爬虫提速的 N 种姿势,你会几种? - 元视角 实现网页长截图的常见思路总结 - 元视角 温故而知新,由 ADO.NET 与 Dapper 所联想到的 - 元视角 视频是不能 P 的系列:OpenCV 人脸检测 - 元视角 作为技术宅的我,是这样追鬼滅の刃的 - 元视角 使用 Python 抽取《半泽直树》原著小说人物关系 - 元视角 厉害了!打工人用 Python 分析西安市职位信息 - 元视角 使用 dotTrace 对 .NET 应用进行性能分析与优化 - 元视角 一道 HashSet 面试题引发的蝴蝶效应 - 元视角 基于选项模式实现.NET Core 的配置热更新 - 元视角 Dapper.Contrib 在 Oracle 环境下引发 ORA-00928 异常问题的解决 - 元视角 .NET Core 中对象池(Object Pool)的使用 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(下):EventBus 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(中):RabbitMQ 篇 - 元视角 利用 MySQL 的 Binlog 实现数据同步与订阅(上):基础篇 - 元视角 记一次从已损坏的 Git 仓库中找回代码的经历 - 元视角 .NET Core 原生 DI 扩展之属性注入实现 - 元视角
AI 时代:聊聊大数据中的 MapReduce - 元视角
飞鸿踏雪 · 2018-01-19 · via 元视角

各位朋友,大家好,我是 Payne,欢迎大家关注我的博客。最近读一本并行计算相关的书籍,在这本书中作者提到了 MapReduce。相信熟悉大数据领域的朋友,一定都知道 MapReduce 是 Hadoop 框架中重要的组成部分。在这篇文章中,博主将以函数式编程作为切入点,来和大家聊一聊大数据中的 MapReduce。如今人工智能正成为行业内竞相追逐的热点,选择 MapReduce 这个主题,更多的是希望带领大家一窥人工智能的门庭,更多深入的话题需要大家来探索和挖掘。

MapReduce 的前世今生

MapReduce 最早是由 Google 公司研究并提出的一种面向大规模数据处理的并行计算模型和方法。2003 年和 2004 年,Google 公司先后在国际会议上发表了关于 Google 分布式文件系统(GFS)和 MapReduce 的论文。这两篇论文公布了 Google 的 GFS 和 MapReduce 的基本原理和主要设计思想,我们通常所说的 Google 的三驾马车,实际上就是在说 GFS、BigTable 和 MapReduce。因此,这些论文的问世直接催生了 Hadoop 的诞生,可以说今天主流的大数据框架如 Hadoop、Spark 等,无一不是受到 Google 这些论文的影响,而这正是 MapReduce 由来,其得名则是因为函数式编程中的两个内置函数: map()和 reduce()。

我们常常说,脱离了业务场景去讨论一项技术是无意义的,这个原则在 MapReduce 上同样适用。众所周知,Google 是一家搜索引擎公司,其设计 MapReduce 的初衷,主要是为了解决搜索引擎中大规模网页数据的并行化处理。所以,我们可以说,MapReduce 其实是起源自 Web 检索的。而我们知道,Web 检索可以分为两部分,即获取网页内容并建立索引、根据网页索引来处理查询关键字。我们可以认为互联网上的每个网页都是一个文档,而每个文档中都会有不同的关键字,Google 会针对每一个关键字建立映射关系,即哪些文档中含有当前关键字,这是建立索引的过程。在建立索引以后,查询就会变得简单,因为现在我们可以按图索骥。

互联网诞生至今,网站及网页的数量越来越庞大,像 Google 这样的搜索引擎巨头是如何保证能够对 Web 上的内容进行检索的呢?答案是采用并行计算(Parallel)。硬件技术的不断革新,让计算机可以发挥多核的优势来处理数据,可当数据量庞大到单机无法处理的程度,就迫使我们不得不采用多台计算机进行并行计算。我们知道并行计算的思想是,将大数据分割成较小的数据块,交由不同的任务单元来处理,然后再将这些结果聚合起来。因此,可以将 MapReduce 理解为一种可以处理海量数据、运行在大规模集群上、具备高度容错能力、以并行处理方式执行的软件框架。MapReduce 是分治思想在大规模机器集群时代的集中体现(如图所示),其中,Mapper 负责任务的划分,Reducer 负责结果的汇总。

MapReduce原理图 MapReduce原理图

MapReduce 的推出给大数据并行处理带来了巨大的革命性影响,使其成为事实上的大数据处理的工业标准,是目前为止最为成功、最广为接受和最易于使用的大数据并行处理技术。广为人知的大数据框架 Hadoop,正是受到 MapReduce 的启发。自问世来,成为 Apache 基金会下最重要的项目,受到全球学术界和工业界的普遍关注,并得到推广和普及应用。MapReduce 的非凡意义在于,它提出了一个基于集群的高性能并行计算模型,允许使用市场上普通的商用服务器构成一个含有数十、数百甚至数千个节点的分布式并行计算集群,可以在集群节点上自动分配和执行任务以及收集计算结果,通过 Mapper 和 Reducer 提供了抽象的大数据处理并行编程接口,可以帮助开发人员更便捷地完成大规模数据处理的编程和计算工作。今天,Google 有超过 10000 个不同的项目已采用 MapReduce 来实现。

函数式编程与 MapReduce

我们提到,MapReduce 之得名,其灵感来自函数式编程中的两个内置函数:map()和 reduce()。函数式编程中,有一个重要的概念叫做高阶函数,是指函数自身能够接受函数,并返回函数的一种函数。我们所熟悉的 C#和 Java 都是典型的面向对象编程(OOP)的语言,在这类编程语言中类(Class)是第一等公民,即不允许有独立于类的结构出现在代码中。虽然微软从未公开表示 C#支持函数式编程,可从 LINQ 中我们依然可以窥见高阶函数的身影,譬如我们熟悉的 Select()、Where()等扩展方法,就可以让我们按照函数式编程的风格去编写代码,这正是为什么 Java 8 开始支持 Stream API 的原因。最经典的函数式编程语言当属 Haskell 语言,我们今天见到的各种编程语言,在考虑引入函数式编程风格的时候,或多或少地都会受到这门语言影响。当你开始适应函数作为第一等公民、高阶函数、柯里化以及惰性求值以后,你或许就会感受到函数式编程特有的美感。

这里我们选择 Python 来阐述函数式编程与 MapReduce 的关系。Python 可以让我们轻易地在多种不同的编程风格间切换,事实上现在的编程语言都有向着混合式编程风格发展的趋势。我们提到 MapReduce 来自两个内置函数:map()和 reduce()。其中,map()方法可以对指定集合中的元素按照指定函数进行映射,并将映射后的结果以集合形式返回。譬如我们有一个集合**[1,3,5,7,9]**,我们希望对集合中的每一个元素做平方运算。借助 Python 中的 map()方法和 lambda 表达式,这个问题可以通过 1 行代码得到解决。同理,如果我们希望对该集合内的元素做求和运算,我们可以借助于 Python 中的 reduce()方法,该方法位于 functools 模块中。在某些编程语言中该方法又被成为 fold()方法,实际上这两种叫法是等价的,我们关注函数式编程的本质即可。什么是本质呢?当然是函数啦。

list = map(lambda x: x * x, [1,3,5,7,9]) #[1,9,25,49,81]
sum = functools.reduce(lambda x,y: x+y, [1,3,5,7,9]) #25

好了,现在我们来分析下这两个函数,这将帮助我们更好地理解 MapReduce。map()方法在这里被称为映射函数,它可以将一种类型映射为一种新的类型。举一个生活中的例子,譬如我们做菜的时候,必不可少的一个环节是将各种各样的食材切碎, 此时作用在这些食材的这个操作就是一个 Map 操作,你给 Map 一个洋葱就可以得到洋葱丝。同样地 ,你给 Map 一个番茄就可以得到番茄块。所以 Map 处理的原始数据,每条数据间没有相互联系,聪明的你告诉我洋葱和番茄有什么关系。相比 map()方法,reduce()方法复杂的地方在于,它要求 lambda 表达式中必须是两个参数。如果继续沿用做菜这个生活化的例子,reduce()方法是将 Map 操作中切好的食材混合在一起。假设我们要做一份辣椒酱,辣椒酱需要的材料有辣椒、姜和蒜,因此在第一步 Map 的时候,这些食材将具有相同的 Key。对同一类数据,我们就可以使用 reduce()进行左/右折叠操作,这相当于我们将同一道菜的食材一起放到锅里,所以 Reduce 阶段处理的数据是以 Key-Value 形式组织的,同一个 Key 下的 Value 具有相关性。这样,从理论上它就完全符合函数式编程里的 map()和 reduce()啦。

C#并行编程里的 PLINQ

关于 MapReduce 中一个经典案例是,统计不同文章中出现的关键字的频率。对这样一个问题,我们基本上可以想到下面四种方法:

  • 写一个单线程程序,顺序地遍历所有文章,然后统计每个关键字出现的频率。
  • 写一个多线程程序,并发地遍历所有文章,然后统计每个关键字出现的频率。
  • 写一个单线程程序,部署到 N 台不同的计算机上,然后将文章分割成 N 份分别输入,再由人工汇总 N 份结果。
  • 使用 MapReduce,程序部署、任务划分、结果汇总全部交给框架去完成,我们定义好任务即可。 通过对比,我们可以非常容易地分析出来,第一种方法最简单同时最耗时;第二种方法理论上比第一种高效,尤其是当计算机是多核或者多处理器的时候,缺点是要解决线程同步的问题;第三种方法初现集群的思想,可无法解决程序部署、任务划分和结果汇总等一系列问题;第四种方法本质上就是第三种方法, 可是 MapReduce 解决了第三种方法全部缺陷,所以它或许是目前最完美的方法。我们下面来考虑,如何模拟这个过程,因为博主不可能为了写一篇科普性质的文章,专门去准备一个 Hadoop 的开发环境啊,哈哈。

PLINQ,即 Parallel LINQ,是.NET 4.0 中增加的任务并行库(TPL)中的一部分。并行编程中有两个基本的概念,任务并行数据并行。前者是指,将程序分割成一组任务并使用不同的线程来运行不同的任务,这种方式被称为任务并行;而后者是指,将数据分割成较小的数据块,对这些数据进行并行计算,然后聚合这些计算结果,这种编程模型称为数据并行。伴随着并行算法的出现,并行集合相继而来,显然 LINQ 的并行版本就是 PLINQ。这里我们来看一个使用 PLINQ 实现的词频统计代码,这将作为我们实现 MapReduce 的一个示例:

//Origin Texts
string strTarget = @"";

//Map
string[] words = strTarget.Split(' '); 
ILookup<string, int> map = words.AsParallel().ToLookup(p => p, k => 1); 

//Reduce
var reduce = from IGrouping<string, int> wordMap in map.AsParallel() 
                 where wordMap.Count() > 1 
                 select new { Word = wordMap.Key, Count = wordMap.Count() }; 

//Show Results
foreach (var word in reduce) 
 Console.WriteLine("Word: '{0}' : Count: {1}", word.Word, word.Count); 

本文小结

今天 Google 发布了全新的 AI 服务工具 Cloud AutoML,从这个产品的名字就可以看出,这是一个试图将人工智能大众化的产品。目前 AI 是行业中不容置疑热点,国外的科技巨头如 Google、微软,国内的科技巨头如腾讯、阿里和百度等,无一不在积极布局 AI 的上下游产业链。最近 CSDN 发布了人工智能方向的发展规划,整个产品线的基本都在做战略上调整,我们这些曾经的老用户被新的社区 运营搞得非常郁闷,因为所有的资源都在向着人工智能和区块链倾斜。上周在知乎上看到一篇讽刺国内区块链发展乱象的文章,大概就是说国人喜欢拿一个 Token 当做加密货币来买,实则连底层技术、分布账本、钱包等基础设施都没有。对于这一点我深有体会,任何新的商业模式在中国都火不过 1 年,譬如在 2017 年里被发扬广大的共享经济,有多少共享单车是靠技术和产品赢得市场的,我相信大部分都是沾了人口基数大的光。目前的人工智能,核心算法及技术都掌握在科技巨头手上。我们所追逐的人工智能,有多少是需要靠不断调整参数反复去训练来达到的呢?我觉得找到切实可靠的需求落脚点,比追逐一个又一个热点要更现实,我们大部分工程师都是在科学家工作的基础上做集成应用,所以拨开泡沫看清方向比盲目跟风更重要呀。

这篇文章蹭了人工智能的热点,其实它对 MapReduce 并没有做多少深入的研究。我们从 Google 的业务场景着手分析,思考为什么 Google 需要 MapReduce,即提出 MapReduce 是为了解决一个什么样的问题?答案是为了适应 Google 在大规模 Web 检索业务方面的需要。通过梳理 Web 检索的一般流程,我们意识到,Web 检索可以分为两部分,即获取网页内容并建立索引、根据网页索引来处理查询关键字,从而引出了 Mapper 和 Reducer 两个基本的数据处理单元,MapReduce 是分治思想在大规模机器集群时代的集中体现,其中,Mapper 负责任务的划分,Reducer 负责结果的汇总。接下来,我们顺着函数式编程的思路,分析了函数式编程中的 map()和 reduce(),这两个核心的函数同 MapReduce 在思想上的一致性,这正是为了印证前文中 MapReduce 得名的由来。考虑到 C#中提供了 PLINQ,而在阅读《C#多线程编程》这本书时,同样提到了 MapReduce 这种并行计算模型,所以在这里将这两者进行结合,提供了一个通过并行计算统计单词频率的简单示例。以上就是这篇文章的所有内容了,如果大家对文章有什么意见或者建议,可以在文章评论区留言,这篇文章就是这样了,谢谢大家,晚安!