Mars——基于矩阵的统一分布式计算框架
背景
Python
Python 是一門相當(dāng)古老的語(yǔ)言了,如今,在數(shù)據(jù)科學(xué)計(jì)算、機(jī)器學(xué)習(xí)、以及深度學(xué)習(xí)領(lǐng)域,Python 越來(lái)越受歡迎。
大數(shù)據(jù)領(lǐng)域,由于 hadoop 和 spark 等,Java 等還是占據(jù)著比較核心的位置,但是在 spark 上也可以看到,pyspark 的用戶占據(jù)很大一部分。
深度學(xué)習(xí)領(lǐng)域,絕大部分的庫(kù)(tensorflow、pytorch、mxnet、chainer)都支持 Python 語(yǔ)言,且 Python 語(yǔ)言也是這些庫(kù)上使用最廣泛的語(yǔ)言。
對(duì) MaxCompute 來(lái)說(shuō),Python 用戶也是一股重要力量。
PyData(numpy、scipy、pandas、scikit-learn、matplotlib)
Python 在數(shù)據(jù)科學(xué)領(lǐng)域,有非常豐富的包可以選擇,下圖展示了整個(gè) Python 數(shù)據(jù)科學(xué)技術(shù)棧。
可以看到 numpy 作為基礎(chǔ),在其上,有 scipy 面向科學(xué)家,pandas 面向數(shù)據(jù)分析,scikit-learn 則是最著名的機(jī)器學(xué)習(xí)庫(kù),matplotlib 專注于可視化。
對(duì) numpy 來(lái)說(shuō),其中最核心的概念就是 ndarray——多維數(shù)組,pandas、scikit-learn 等庫(kù)都構(gòu)建于這個(gè)數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)之上。
問(wèn)題
雖然 Python 在這些領(lǐng)域越來(lái)越流行,PyData 技術(shù)棧給數(shù)據(jù)科學(xué)家們提供了多維矩陣、DataFrame 上的分析和計(jì)算能力、基于二維矩陣的機(jī)器學(xué)習(xí)算法,但這些庫(kù)都僅僅受限于單機(jī)運(yùn)算,在大數(shù)據(jù)時(shí)代,數(shù)據(jù)量一大,這些庫(kù)的處理能力都顯得捉襟見(jiàn)肘。
雖然大數(shù)據(jù)時(shí)代,有各種各樣基于 SQL 的計(jì)算引擎,但對(duì)科學(xué)計(jì)算領(lǐng)域,這些引擎都不太適合用來(lái)進(jìn)行大規(guī)模的多維矩陣的運(yùn)算操作。而且,相當(dāng)一部分用戶,尤其是數(shù)據(jù)科學(xué)家們,習(xí)慣于使用各種成熟的單機(jī)庫(kù),他們不希望改變自己的使用習(xí)慣,去學(xué)習(xí)一些新的庫(kù)和語(yǔ)法。
此外,在深度學(xué)習(xí)領(lǐng)域,ndarray/tensor 也是最基本的數(shù)據(jù)結(jié)構(gòu),但它們僅僅限制在深度學(xué)習(xí)上,也不適合大規(guī)模的多維矩陣運(yùn)算。
基于這些考量,我們開(kāi)發(fā)了 Mars,一個(gè)基于 tensor 的統(tǒng)一分布式計(jì)算框架,前期我們關(guān)注怎么將 tensor 這層做到極致。
我們的工作
Mars 的核心用 python 實(shí)現(xiàn),這樣做的好處是能利用到現(xiàn)有的 Python 社區(qū)的工作,我們能充分利用 numpy、cupy、pandas 等來(lái)作為我們小的計(jì)算單元,我們能快速穩(wěn)定構(gòu)建我們整個(gè)系統(tǒng);其次,Python 本身能輕松和 c/c++ 做繼承,我們也不必?fù)?dān)心 Python 語(yǔ)言本身的性能問(wèn)題,我們可以對(duì)性能熱點(diǎn)模塊輕松用 c/cython 重寫。
接下來(lái),主要集中介紹 Mars tensor,即多維矩陣計(jì)算的部分。
Numpy API
Numpy 成功的一個(gè)原因,就是其簡(jiǎn)單易用的 API。Mars tensor 在這塊可以直接利用其作為我們的接口。所以在 numpy API 的基礎(chǔ)上,用戶可以寫出靈活的代碼,進(jìn)行數(shù)據(jù)處理,甚至是實(shí)現(xiàn)各種算法。
下面是兩段代碼,分別是用 numpy 和 Mars tensor 來(lái)實(shí)現(xiàn)一個(gè)功能。
import numpy as npa = np.random.rand(1000, 2000) (a + 1).sum(axis=1) import mars.tensor as mta = mt.random.rand(1000, 2000) (a + 1).sum(axis=1).execute()這里,創(chuàng)建了一個(gè) 1000x2000 的隨機(jī)數(shù)矩陣,對(duì)其中每個(gè)元素加1,并在 axis=1(行)上求和。
目前,Mars 實(shí)現(xiàn)了大約 70% 的 Numpy 常用接口。
可以看到,除了 import 做了替換,用戶只需要通過(guò)調(diào)用 execute 來(lái)顯式觸發(fā)計(jì)算。通過(guò) execute 顯式觸發(fā)計(jì)算的好處是,我們能對(duì)中間過(guò)程做更多的優(yōu)化,來(lái)更高效地執(zhí)行計(jì)算。
不過(guò),靜態(tài)圖的壞處是犧牲了靈活性,增加了 debug 的難度。下個(gè)版本,我們會(huì)提供 instant/eager mode,來(lái)對(duì)每一步操作觸發(fā)計(jì)算,這樣,用戶能更有效地進(jìn)行 debug,且能利用到 Python 語(yǔ)言來(lái)做循環(huán),當(dāng)然性能也會(huì)有所損失。
使用 GPU 計(jì)算
Mars tensor 也支持使用 GPU 計(jì)算。對(duì)于某些矩陣創(chuàng)建的接口,我們提供了?gpu=True?的選項(xiàng),來(lái)指定分配到 GPU,后續(xù)這個(gè)矩陣上的計(jì)算將會(huì)在 GPU 上進(jìn)行。
import mars.tensor as mta = mt.random.rand(1000, 2000, gpu=True) (a + 1).sum(axis=1).execute()這里?a?是分配在 GPU 上,因此后續(xù)的計(jì)算在 GPU 上進(jìn)行。
稀疏矩陣
Mars tensor 支持創(chuàng)建稀疏矩陣,不過(guò)目前 Mars tensor 還只支持二維稀疏矩陣。比如,我們可以創(chuàng)建一個(gè)稀疏的單位矩陣,通過(guò)指定?sparse=True?即可。
import mars.tensor as mta = mt.eye(1000, sparse=True, gpu=True) b = (a + 1).sum(axis=1)這里看到,gpu 和 sparse 選項(xiàng)可以同時(shí)指定。
基于 Mars tensor 的上層建筑
這部分在 Mars 里尚未實(shí)現(xiàn),這里提下我們希望在 Mars 上構(gòu)建的各個(gè)組件。
DataFrame
相信有部分同學(xué)也知道 PyODPS DataFrame,這個(gè)庫(kù)是我們之前的一個(gè)項(xiàng)目,它能讓用戶寫出類似 pandas 類似的語(yǔ)法,讓運(yùn)算在 ODPS 上進(jìn)行。但 PyODPS DataFrame 由于 ODPS 本身的限制,并不能完全實(shí)現(xiàn) pandas 的全部功能(如 index 等),而且語(yǔ)法也有不同。
基于 Mars tensor,我們提供 100% 兼容 pandas 語(yǔ)法的 DataFrame。使用 mars DataFrame,不會(huì)受限于單個(gè)機(jī)器的內(nèi)存。這個(gè)是我們下個(gè)版本的最主要工作之一。
機(jī)器學(xué)習(xí)
scikit-learn 的一些算法的輸入就是二維的 numpy ndarray。我們也會(huì)在 Mars 上提供分布式的機(jī)器學(xué)習(xí)算法。我們大致有以下三條路:
細(xì)粒度的函數(shù)和類
Mars 的核心,其實(shí)是一個(gè)基于 Actor 的細(xì)粒度的調(diào)度引擎。因此,實(shí)際上,用戶可以寫一些并行的 Python 函數(shù)和類,來(lái)進(jìn)行細(xì)粒度的控制。我們可能會(huì)提供以下幾種接口。
函數(shù)
用戶能寫普通的 Python 函數(shù),通過(guò)?mars.remote.spawn?來(lái)將函數(shù)調(diào)度到 Mars 上來(lái)分布式運(yùn)行
import mars.remote as mrdef add(x, y):return x + ydata = [(1, 2),(3, 4) ]for item in data:mr.spawn(add, item[0], item[1])利用?mr.spawn,用戶能輕松構(gòu)建分布式程序。在函數(shù)里,用戶也可以使用 mr.spawn,這樣,用戶可以寫出非常精細(xì)的分布式執(zhí)行程序。
類
有時(shí)候,用戶需要一些有狀態(tài)的類,來(lái)進(jìn)行更新?tīng)顟B(tài)等操作,這些類在 Mars 上被稱為 RemoteClass。
import mars.remote as mrclass Counter(mr.RemoteClass):def __init__(self):self.value = 0def inc(self, n=1):self.value += ncounter = mr.spawn(Counter) counter.inc()目前,這些函數(shù)和類的部分尚未實(shí)現(xiàn),只是在構(gòu)想中,所以屆時(shí)接口可能會(huì)做調(diào)整。
內(nèi)部實(shí)現(xiàn)
這里,我簡(jiǎn)單介紹下 Mars tensor 的內(nèi)部原理。
客戶端
在客戶端,我們不會(huì)做任何真正的運(yùn)算操作,用戶寫下代碼,我們只會(huì)在內(nèi)存里用圖記錄用戶的操作。
對(duì)于 Mars tensor 來(lái)說(shuō),我們有兩個(gè)重要的概念,operand 和 tensor,分別如下圖的藍(lán)色圓和粉色方塊所示。Operand 表示算子,tensor 表示生成的多維數(shù)組。
比如,下圖,用戶寫下這些代碼,我們會(huì)依次在圖上生成對(duì)應(yīng)的 operand 和 tensor。
當(dāng)用戶顯式調(diào)用?execute?的時(shí)候,我們會(huì)將這個(gè)圖提交到 Mars 的分布式執(zhí)行環(huán)境。
我們客戶端部分,并不會(huì)對(duì)語(yǔ)言有任何依賴,只需要有相同的 tensor graph 序列化,因此可以用任何語(yǔ)言實(shí)現(xiàn)。下個(gè)版本我們要不要提供 Java 版本的 Mars tensor,我們還要看是不是有用戶需要。
分布式執(zhí)行環(huán)境
Mars 本質(zhì)上是一個(gè)對(duì)細(xì)粒度圖的執(zhí)行調(diào)度系統(tǒng)。
對(duì)于 Mars tensor 來(lái)說(shuō),我們接收到了客戶端的 tensor 級(jí)別的圖(粗粒度),我們要嘗試將其轉(zhuǎn)化成 chunk 級(jí)別的圖(細(xì)粒度)。每個(gè) chunk 以及其輸入,在執(zhí)行時(shí),都應(yīng)當(dāng)能被內(nèi)存放下。我們稱這個(gè)過(guò)程叫做 tile。
在拿到細(xì)粒度的 chunk 級(jí)別的圖后,我們會(huì)將這個(gè)圖上的 Operand 分配到各個(gè) worker 上去執(zhí)行。
總結(jié)
Mars 在九月份的云棲大會(huì)發(fā)布,目前我們已經(jīng)在 Github 開(kāi)源:https://github.com/mars-project/mars?。我們項(xiàng)目完全以開(kāi)源的方式運(yùn)作,而不是簡(jiǎn)單把代碼放出來(lái)。
期待有更多的同學(xué)能參與 Mars,共建 Mars。
努力了很久,我們不會(huì)甘于做一個(gè)平庸的項(xiàng)目,我們期待對(duì)世界做出一點(diǎn)微小的貢獻(xiàn)——我們的征途是星辰大海!
?
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的Mars——基于矩阵的统一分布式计算框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: “阿里巴巴小程序繁星计划”:20亿扶持2
- 下一篇: 多维度创新打造领先阿里云技术生态