Mars 是什么、能做什么、如何做的——记 Mars 在 PyCon China 2018 上的分享
最近,在 PyCon China 2018 的北京主會(huì)場(chǎng)、成都和杭州分會(huì)場(chǎng)都分享了我們最新的工作 Mars,基于矩陣的統(tǒng)一計(jì)算框架。本文會(huì)以文字的形式對(duì) PyCon 中國(guó)上的分享再進(jìn)行一次闡述。
聽(tīng)到 Mars,很多第一次聽(tīng)說(shuō)的同學(xué)都會(huì)靈魂三問(wèn):Mars 是什么,能做什么,怎么做的。今天我們就會(huì)從背景,以及一個(gè)例子出發(fā),來(lái)回答這幾個(gè)問(wèn)題。
背景
首先是 scipy 技術(shù)棧的全景圖,numpy 是基礎(chǔ),它提供了多維數(shù)組的數(shù)據(jù)結(jié)構(gòu),并提供了它上面的各種計(jì)算。再往上,重要的有 scipy,主要面向各種科學(xué)計(jì)算的操作;pandas,其中核心的概念是 DataFrame,他提供對(duì)表類(lèi)型數(shù)據(jù)的處理、清洗等功能。往上一層,比較經(jīng)典的庫(kù),有 scikit-learn,它是最知名的機(jī)器學(xué)習(xí)框架之一。最上面一層,是各種垂直領(lǐng)域的庫(kù),如 astropy 主要面向天文,biopython 面向生物領(lǐng)域等。
從 scipy 技術(shù)棧可以看出,numpy 是一個(gè)核心的地位,大量上層的庫(kù)都使用了 numpy 的數(shù)據(jù)結(jié)構(gòu)和計(jì)算。
我們真實(shí)世界的數(shù)據(jù),并不只是表這種二維類(lèi)型數(shù)據(jù)那么簡(jiǎn)單,很多時(shí)候,我們要面對(duì)的往往是多維數(shù)據(jù),比如我們常見(jiàn)的圖片處理,首先我們有圖片的個(gè)數(shù),然后有圖片的長(zhǎng)寬,以及 RGBA 通道,這就是四維的數(shù)據(jù);這樣的例子不勝枚舉。有這樣多維的處理能力,就有處理各種更加復(fù)雜,甚至是科學(xué)領(lǐng)域的能力;同時(shí),由于多維數(shù)據(jù)本身包含二維數(shù)據(jù),所以,我們也因此具備表類(lèi)型數(shù)據(jù)的處理能力。
另外,如果我們需要探究數(shù)據(jù)的內(nèi)在,光靠對(duì)表數(shù)據(jù)進(jìn)行一些統(tǒng)計(jì)等操作是絕對(duì)不夠的,我們需要更深層的“數(shù)學(xué)” 的方法,比如運(yùn)用矩陣乘法、傅里葉變換等等的能力,來(lái)對(duì)數(shù)據(jù)進(jìn)行更深層次的分析。而 numpy 由于是數(shù)值計(jì)算的庫(kù),加上各種上層的庫(kù),我們認(rèn)為它們很適合用來(lái)提供這方面的能力。
為什么要做 Mars,從一個(gè)例子開(kāi)始
那么,為什么要做 Mars 這個(gè)項(xiàng)目呢?我們不妨從一個(gè)例子來(lái)看。
我們?cè)噲D用蒙特卡洛方法來(lái)求解 pi,蒙特卡洛方法其實(shí)很簡(jiǎn)單,就是用隨機(jī)數(shù)的方法來(lái)解決特定的問(wèn)題。如圖,這里我們有個(gè)半徑為1的圓和邊長(zhǎng)為2的正方形,我們生成很多隨機(jī)點(diǎn)的方式,通過(guò)右下角的公式,我們就可以計(jì)算出 pi 的值為 4 乘以落在圓里點(diǎn)的個(gè)數(shù)除以總的點(diǎn)個(gè)數(shù)。隨機(jī)生成的點(diǎn)越多,計(jì)算出來(lái)的 pi 就越精確。
用純 Python 實(shí)現(xiàn)非常簡(jiǎn)單,我們只要遍歷 N 次,生成 x 和 y 點(diǎn),計(jì)算是不是落在圓內(nèi)即可。運(yùn)行1千萬(wàn)個(gè)點(diǎn),需要超過(guò)10秒的時(shí)間。
Cython 是常見(jiàn)加速 Python 代碼的方式,Cython 定義了 Python 語(yǔ)言的超集,把這個(gè)語(yǔ)言翻譯到 c/c++,然后再進(jìn)行編譯來(lái)加速執(zhí)行。這里,我們?cè)黾恿藥讉€(gè)變量的類(lèi)型,可以看到比純 Python 提升了 40% 的性能。
Cython 現(xiàn)在已經(jīng)成為 Python 項(xiàng)目的標(biāo)配,核心的 Python 三方庫(kù)基本都使用 Cython 來(lái)加速 Python 代碼的性能。
我們這個(gè)例子里的數(shù)據(jù)都是一個(gè)類(lèi)型,我們可以想到用專(zhuān)門(mén)的數(shù)值計(jì)算的庫(kù),通過(guò)矢量化的方式,能極快加速這個(gè)任務(wù)的性能。numpy 就是當(dāng)仁不讓的選擇了,使用 numpy,我們需要的是面向 array 的思維方式,我們應(yīng)當(dāng)減少使用循環(huán)。這里先用?numpy.random.uniform?來(lái)生成 N*2 的一個(gè)二維數(shù)組,然后?data ** 2?會(huì)對(duì)該數(shù)組里的所有數(shù)據(jù)做平方操作,然后?sum(axis=1)?,會(huì)對(duì) axis=1 也就是行方向上求和,這個(gè)時(shí)候,得到的是長(zhǎng)度為 N 的 vector,然后我們用?numpy.sqrt?來(lái)對(duì)這個(gè) vector 的每一個(gè)值求開(kāi)方,<1 會(huì)得到一個(gè)布爾值的 vector,即每個(gè)點(diǎn)是不是都是落在圓里,最后接一個(gè) sum,就可以求出來(lái)總共的點(diǎn)的個(gè)數(shù)。初次上手 numpy 可能會(huì)不太習(xí)慣,但是用多了以后,就會(huì)發(fā)現(xiàn)這種寫(xiě)法的方便,它其實(shí)是非常符合直覺(jué)的。
可以看到,通過(guò)使用 numpy,我們寫(xiě)出了更簡(jiǎn)單的代碼,但是性能確大幅提升,比純 Python 的寫(xiě)法性能提升超過(guò) 10 倍。
那么 numpy 的代碼還能夠優(yōu)化么,答案是肯定的,我們通過(guò)一個(gè)叫 numexpr 的庫(kù),來(lái)將 numpy 的多個(gè)操作合并成一個(gè)操作執(zhí)行,來(lái)加速 numpy 的執(zhí)行。
可以看到,通過(guò) numexpr 優(yōu)化的代碼,性能比純 Python 代碼提升超過(guò) 25 倍。
此時(shí)的代碼運(yùn)行已經(jīng)相當(dāng)快了,如果我們手上有 GPU,那么我們可以利用硬件來(lái)加速任務(wù)執(zhí)行。
這里必須要安利一個(gè)庫(kù),叫?cupy,他提供了和 numpy 一致的 API,通過(guò)簡(jiǎn)單的 import 替換,就能讓 numpy 代碼跑在英偉達(dá)的顯卡之上。
這時(shí)可以看到,性能大幅提升超過(guò) 270 倍。真的非常夸張了。
為了讓蒙特卡洛方法計(jì)算的結(jié)果更加精確,我們把計(jì)算量擴(kuò)大 1000 倍。會(huì)碰到什么情況呢?
沒(méi)錯(cuò),這就是大家不時(shí)碰到的,OutOfMemory,內(nèi)存溢出。更慘的是,在 jupyter 里,有時(shí)候內(nèi)存溢出導(dǎo)致進(jìn)程被殺,甚至?xí)?dǎo)致之前跑的全部結(jié)果都丟失。
蒙特卡洛方法還是比較容易處理的,我把問(wèn)題分解成 1000 個(gè),每個(gè)求解1千萬(wàn)數(shù)據(jù)就好了嘛,寫(xiě)個(gè)循環(huán),做個(gè)匯總。但此時(shí),整個(gè)計(jì)算的時(shí)間來(lái)到了12分鐘多,太慢了。
此時(shí)我們會(huì)發(fā)現(xiàn),整個(gè)運(yùn)行過(guò)程中,其實(shí)只有一個(gè) CPU 在干活,其他核都在原地吆喝。那么,我們?cè)趺醋?numpy 并行化呢?
首先,numpy 里有一些操作是能并行的,比如 tensordot 來(lái)做矩陣乘法,其他大部分操作都不能利用多核。那么,要將 numpy 并行化,我們可以:
蒙特卡洛方法算 pi 改寫(xiě)成多線程和多進(jìn)程實(shí)現(xiàn)還是非常容易的,我們寫(xiě)一個(gè)函數(shù)來(lái)處理1千萬(wàn)的數(shù)據(jù),我們把這個(gè)函數(shù)通過(guò) concurrent.futures 的 ThreadPoolExecutor 和 ProcessPoolExecutor 來(lái)分別提交函數(shù) 1000 遍用多線程和多進(jìn)程執(zhí)行即可。可以看到性能能提升到 2倍和3倍。
但是呢,蒙特卡洛求解 pi 本身就很容易手寫(xiě)并行,考慮更復(fù)雜的情況。
import numpy as npa = np.random.rand(100000, 100000) (a.dot(a.T) - a).std()這里創(chuàng)建了 10萬(wàn)*10萬(wàn)的矩陣 a,輸入就有大概 75G,我們拿 a 矩陣乘 a 的轉(zhuǎn)置,再減去 a 本身,最終求標(biāo)準(zhǔn)差。這個(gè)任務(wù)的輸入數(shù)據(jù)就很難塞進(jìn)內(nèi)存,后續(xù)的手寫(xiě)并行就更加困難。
這里問(wèn)題就引出來(lái)了,我們需要什么樣框架呢?
Mars 是什么,能做什么事
Mars 就是這樣一個(gè)框架,它的目標(biāo)就是解決這幾個(gè)問(wèn)題。目前 Mars 包括了 tensor :分布式的多維矩陣計(jì)算。
100億大小的蒙特卡洛求解 pi的問(wèn)題規(guī)模是 150G,它會(huì)導(dǎo)致 OOM。通過(guò) Mars tensor API,只需要將?import numpy as np?替換成?import mars.tensor as mt,后續(xù)的計(jì)算完全一致。不過(guò)有一個(gè)不同,mars tensor 需要通過(guò)?execute?觸發(fā)執(zhí)行,這樣做的好處是能夠?qū)φ麄€(gè)中間過(guò)程做盡量多的優(yōu)化,比如操作合并等等。不過(guò)這種方式對(duì) debug 不太友好,后續(xù)我們會(huì)提供 eager mode,來(lái)對(duì)每一步操作都觸發(fā)計(jì)算,這樣就和 numpy 代碼完全一致了。
可以看到這個(gè)計(jì)算時(shí)間和手寫(xiě)并行時(shí)間相當(dāng),峰值內(nèi)存使用也只是 1個(gè)多G,因此可以看到 Mars tensor?既能充分并行,又能節(jié)省內(nèi)存的使用?。
目前,Mars 實(shí)現(xiàn)了 70% 的常見(jiàn) numpy 接口,完整列表見(jiàn)?這里。我們一致在努力提供更多 numpy 和 scipy 的接口,我們最近剛剛完成了對(duì)逆矩陣計(jì)算的支持。
Mars tensor 也提供了對(duì) GPU 和稀疏矩陣的支持。eye?是創(chuàng)建單位對(duì)角矩陣,它只有對(duì)角線上有值為1,如果用稠密的方式存儲(chǔ)會(huì)浪費(fèi)存儲(chǔ)。不過(guò)目前,Mars tensor 還只支持二維稀疏矩陣。
Mars 怎么做到并行和更省內(nèi)存
和所有的 dataflow 的框架一樣,Mars 本身也有計(jì)算圖的概念,不同的是,Mars 包含粗粒度圖和細(xì)粒度圖的概念,用戶寫(xiě)的代碼在客戶端生成粗粒度圖,在提交到服務(wù)端后,會(huì)有?tile?的過(guò)程,將粗粒度圖 tile 成細(xì)粒度圖,然后我們會(huì)調(diào)度細(xì)粒度圖執(zhí)行。
這里,用戶寫(xiě)下的代碼,在內(nèi)存里會(huì)表達(dá)成 Tensor 和 Operand 構(gòu)成的粗粒度圖。
當(dāng)用戶調(diào)用?execute?方法時(shí),粗粒度的圖會(huì)被序列化到服務(wù)端,反序列化后,我們會(huì)把這個(gè)圖 tile 成細(xì)粒度圖。對(duì)于輸入 10002000 的矩陣,假設(shè)指定每個(gè)維度上的 chunk 大小都是 500,那它會(huì)被 tile 成 24 一共 8 個(gè)chunk。
后續(xù),我們會(huì)對(duì)每個(gè)我們實(shí)現(xiàn)的 operand 也就是算子提供 tile 的操作,將一個(gè)粗粒度的圖 tile 成細(xì)粒度圖。這時(shí),我們可以看到,在單機(jī),如果有8個(gè)核,那么我們就可以并行執(zhí)行整個(gè)細(xì)粒度圖;另外給定 1/8 大小的內(nèi)存,我們就可以完成整個(gè)圖的計(jì)算。
不過(guò),我們?cè)谡嬲龍?zhí)行前,會(huì)對(duì)整個(gè)圖進(jìn)行 fuse 也就是操作合并的優(yōu)化,這里的三個(gè)操作真正執(zhí)行的時(shí)候,會(huì)被合并成一個(gè)算子。針對(duì)執(zhí)行目標(biāo)的不同,我們會(huì)使用 numexpr 和 cupy 的 fuse 支持來(lái)分別對(duì) CPU 和 GPU 進(jìn)行操作合并執(zhí)行。
上面的例子,都是我們?cè)斐鰜?lái)很容易并行的任務(wù)。如我們先前提到的例子,通過(guò) tile 之后生成的細(xì)粒度圖其實(shí)是非常復(fù)雜的。真實(shí)世界的計(jì)算場(chǎng)景,這樣的任務(wù)其實(shí)是很多的。
為了將這些復(fù)雜的細(xì)粒度圖能夠充分調(diào)度執(zhí)行,我們必須要滿足一些基本的準(zhǔn)則,才能讓執(zhí)行足夠高效。
首先,初始節(jié)點(diǎn)的分配非常重要。比如上圖,假設(shè)我們有兩個(gè) worker,如果我們把 1和3 分配到一個(gè) worker,而將 2和4 分配到另一個(gè) worker,這時(shí)當(dāng) 5 或者 6 被調(diào)度的時(shí)候,他們就需要觸發(fā)遠(yuǎn)程數(shù)據(jù)拉取,這樣執(zhí)行效率會(huì)大打折扣。如果我們一開(kāi)始將 1和2 分配到一個(gè) worker,將 3和4 分配到另一個(gè) worker,這時(shí)執(zhí)行就會(huì)非常高效。初始節(jié)點(diǎn)的分配對(duì)整體的執(zhí)行影響是很大的,這就需要我們對(duì)整個(gè)細(xì)粒度的圖有個(gè)全局的掌握,我們才能做到比較好的初始節(jié)點(diǎn)分配。
另外,深度優(yōu)先執(zhí)行的策略也是相當(dāng)重要的。假設(shè)這時(shí),我們只有一個(gè) worker,執(zhí)行完 1和2 后,我們調(diào)度了 3 的話,就會(huì)導(dǎo)致 1和2 的內(nèi)存不能釋放,因?yàn)?5 此時(shí)還沒(méi)有被觸發(fā)執(zhí)行。但是,如果我們執(zhí)行完 1和2 后,調(diào)度了 5 執(zhí)行,那么當(dāng) 5 執(zhí)行完后,1和2 的內(nèi)存就可以釋放,這樣整個(gè)執(zhí)行過(guò)程中的內(nèi)存就會(huì)是最省的。
所以,初始節(jié)點(diǎn)分配,以及深度優(yōu)先執(zhí)行是兩個(gè)最基本的準(zhǔn)則,光有這兩點(diǎn)是遠(yuǎn)遠(yuǎn)不夠的,mars 的整個(gè)執(zhí)行調(diào)度中有很多具有挑戰(zhàn)的任務(wù),這也是我們需要長(zhǎng)期優(yōu)化的對(duì)象。
Mars 分布式
所以,Mars 本質(zhì)上其實(shí)是一個(gè)細(xì)粒度的,異構(gòu)圖的調(diào)度系統(tǒng)。我們把細(xì)粒度的算子調(diào)度到各個(gè)機(jī)器上,在真正執(zhí)行的時(shí)候其實(shí)是調(diào)用 numpy、cupy、numexpr 等等的庫(kù)。我們充分利用了成熟的、高度優(yōu)化的單機(jī)庫(kù),而不是重復(fù)在這些領(lǐng)域造輪子。
在這個(gè)過(guò)程中,我們會(huì)遇到一些難點(diǎn):
我們的解法是使用 Actor model。Actor模型定義了并行的方式,也就是一切皆 Actor,每個(gè) Actor 維護(hù)一個(gè)內(nèi)部狀態(tài),它們都持有郵箱,Actor 之間通過(guò)消息傳遞,消息收到會(huì)放在郵箱中,Actor 從郵箱中取消息進(jìn)行處理,一個(gè) Actor 同時(shí)只能處理一個(gè)消息。Actor 就是一個(gè)最小的并行單元,由于一個(gè) Actor 同時(shí)只能處理一個(gè)消息,你完全不需要擔(dān)心并發(fā)的問(wèn)題,并發(fā)應(yīng)當(dāng)是 Actor 框架來(lái)處理的。而所有 Actor 是不是在同一臺(tái)機(jī)器上,這在 Actor 模型里也變得不重要,Actor 在不同機(jī)器上,只要能完成消息的傳遞就可以了,這樣 Actor 模型也天然支持分布式系統(tǒng)。
因?yàn)?Actor 是最小的并行單元,我們?cè)趯?xiě)代碼的時(shí)候,可以將整個(gè)系統(tǒng)分解成很多 Actor,每個(gè) Actor 是單一職責(zé)的,這有點(diǎn)類(lèi)似面向?qū)ο蟮乃枷?#xff0c;這樣讓我們的代碼得以解耦。
另外,Master 解耦成 Actor 之后,我們可以讓這些 Actor 分布在不同的機(jī)器上,這樣就讓 Master 不再成為單點(diǎn)。同時(shí),我們讓這些 Actor 根據(jù)一致性哈希來(lái)進(jìn)行分配,后續(xù)如果有 scheduler 機(jī)器掛掉, Actor 可以根據(jù)一致性哈希重新分配并重新創(chuàng)建來(lái)達(dá)到容錯(cuò)的目的。
最后,我們的 actors 是跑在多進(jìn)程上的,每個(gè)進(jìn)程里是很多的協(xié)程,這樣,我們的 worker 也不會(huì)受到 GIL 的限制。
像 Scala 或者 Java 這些 JVM 語(yǔ)言 可以使用 akka 這個(gè) Actor 框架,對(duì)于 Python 來(lái)說(shuō),我們并沒(méi)有什么標(biāo)準(zhǔn)做法,我們認(rèn)為我們只是需要一個(gè)輕量的 Actor 框架就可以滿足我們使用,我們不需要 akka 里面一些高階的功能。因此,我們開(kāi)發(fā)了 Mars actors,一個(gè)輕量的 Actor 框架,我們 Mars 整個(gè)分布式的 schedulers 和 workers 都在 Mars actors 層之上。
這是我們 Mars actors 的架構(gòu)圖,在啟動(dòng) Actor pool 的時(shí)候,我們子進(jìn)程會(huì)根據(jù)并發(fā)啟動(dòng)若干子進(jìn)程。主進(jìn)程上有 socket handler 來(lái)接受遠(yuǎn)程 socket 連接傳遞消息,另外主進(jìn)程有個(gè) Dispatcher 對(duì)象,用來(lái)根據(jù)消息的目的地來(lái)進(jìn)行分發(fā)。我們所有的 Actor 都在子進(jìn)程上創(chuàng)建,當(dāng) Actor 收到一個(gè)消息處理時(shí),我們會(huì)通過(guò)協(xié)程調(diào)用?Actor.on_receive(message)?方法。
一個(gè) Actor 發(fā)送消息到另一個(gè) Actor,分三種情況。
由于使用協(xié)程作為子進(jìn)程內(nèi)的并行方式,而協(xié)程本身在 IO 處理上有很強(qiáng)的性能,所以,我們的 Actor 框架在 IO 方面也會(huì)有很好的性能。
上圖是裸用 Mars actors 來(lái)求解蒙特卡洛方法算 pi。這里定義兩個(gè) Actor,一個(gè) Actor 是 ChunkInside,它接受一個(gè) chunk 的大小,來(lái)計(jì)算落在圓內(nèi)點(diǎn)的個(gè)數(shù);另外一個(gè) Actor 是 PiCaculator,它負(fù)責(zé)接受總的點(diǎn)個(gè)數(shù),來(lái)創(chuàng)建 ChunkInside,這個(gè)例子就是直接創(chuàng)建 1000 個(gè) ChunkInside,然后通過(guò)發(fā)送消息來(lái)觸發(fā)他們計(jì)算。create_actor?時(shí)指定 address 可以讓 Actor 分配在不同的機(jī)器上。
這里可以看到,我們裸用 Mars actors 的性能是要快過(guò)多進(jìn)程版本的。
這里我們總結(jié)一下,通過(guò)使用 Mars actors,我們能不受 GIL 限制,編寫(xiě)分布式代碼變得非常容易,它讓我們 IO 變得高效,此外,因?yàn)?Actor 解耦,代碼也變得更容易維護(hù)。
現(xiàn)在讓我們看下 Mars 分布式的完整執(zhí)行過(guò)程。現(xiàn)在有1個(gè) client,3個(gè) scheduler 和 5個(gè)worker。用戶創(chuàng)建一個(gè) session,在服務(wù)端會(huì)創(chuàng)建一個(gè) SessionActor 對(duì)象,通過(guò)一致性哈希,分配到 scheduler1 上。此時(shí),用戶運(yùn)行了一個(gè) tensor,首先 SessionActor 會(huì)創(chuàng)建一個(gè) GraphActor,它會(huì) tile 粗粒度圖,圖上假設(shè)有三個(gè)節(jié)點(diǎn),則會(huì)創(chuàng)建三個(gè) OperandActor,分別分配到不同的 scheduler 上。每個(gè) OperandActor 會(huì)控制 operand 的提交、任務(wù)狀態(tài)的監(jiān)督和內(nèi)存的釋放等操作。此時(shí) 1 和 2 的 OperandActor 發(fā)現(xiàn)沒(méi)有依賴,并且集群資源充足,那么他們會(huì)把任務(wù)提交到相應(yīng)的 worker 執(zhí)行,在執(zhí)行完成后,向 3 通知任務(wù)完成,3 發(fā)現(xiàn) 1和2 都執(zhí)行完成后,因?yàn)閿?shù)據(jù)在不同 worker 執(zhí)行,決定好執(zhí)行 worker 后,先觸發(fā)數(shù)據(jù)拉取操作,然后再執(zhí)行。客戶端這邊,通過(guò)輪詢 GraphActor 得知任務(wù)完成,則會(huì)觸發(fā)數(shù)據(jù)拉取到本地的操作。整個(gè)任務(wù)就完成了。
我們對(duì) Mars 分布式做了兩個(gè) benchmark,第一個(gè)是對(duì) 36 億數(shù)據(jù)的每個(gè)元素加一再乘以2,圖中紅色叉是 numpy 的執(zhí)行時(shí)間,可以看到,我們比 numpy 有數(shù)倍提升,藍(lán)色的虛線是理論運(yùn)行時(shí)間,可以看到我們真實(shí)加速非常接近理論時(shí)間加速。第二個(gè) benchmark,我們?cè)黾恿藬?shù)據(jù)量,來(lái)到 144 億數(shù)據(jù),對(duì)每個(gè)元素加1乘以2后,再求和,可以看到單機(jī) numpy 已經(jīng)不能完成任務(wù)了,此時(shí),針對(duì)這個(gè)任務(wù),我們也可以取得不錯(cuò)的加速比。
未來(lái)計(jì)劃
Mars 已經(jīng)在 Github 上源代碼,讓更多同學(xué)來(lái)一起參與共建 Mars:https://github.com/mars-project/mars?。
在后續(xù) Mars 的開(kāi)發(fā)計(jì)劃上,如上文說(shuō),我們會(huì)支持 eager mode,讓每一步觸發(fā)執(zhí)行,提升對(duì)性能不敏感的任務(wù)開(kāi)發(fā)以及 debug 時(shí)的使用體驗(yàn);我們會(huì)支持更多 numpy 和 scipy 接口;后續(xù)很重要的一個(gè)是,我們會(huì)提供 100% 兼容 pandas 的接口,由于利用了 mars tensor 作為基礎(chǔ),我們也可以提供 GPU 的支持;我們會(huì)提供兼容 scikit-learn 的機(jī)器學(xué)習(xí)的支持;我們還會(huì)提供在細(xì)粒度圖上調(diào)度自定義函數(shù)和自定義類(lèi)的功能,增強(qiáng)靈活性;最后,因?yàn)槲覀兛蛻舳似鋵?shí)并不依賴 Python,任意語(yǔ)言都可以序列化粗粒度圖,所以我們完全可以提供多語(yǔ)言的客戶端版本,不過(guò)這點(diǎn),我們會(huì)視需求而定。
總之,開(kāi)源對(duì)我們是很重要的,龐大的 scipy 技術(shù)棧的并行化,光靠我們的力量是不夠的,需要大家來(lái)一起幫我們來(lái)共建。
現(xiàn)場(chǎng)圖片
最后再 po 一點(diǎn)現(xiàn)場(chǎng)圖片吧,現(xiàn)場(chǎng)觀眾對(duì) Mars 的問(wèn)題還是蠻多的。我大致總結(jié)下:
?
?
?
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的Mars 是什么、能做什么、如何做的——记 Mars 在 PyCon China 2018 上的分享的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 生物智能与AI——关乎创造、关乎理解(下
- 下一篇: 基于MaxCompute的数仓数据质量管