快手 Dragonfly 策略引擎的設(shè)計(jì)與應(yīng)用
一、問題與挑戰(zhàn)
1、問題背景
從 2018 年開始,快手的整個(gè)業(yè)務(wù)呈現(xiàn)快速發(fā)展的狀態(tài),團(tuán)隊(duì)也在快速擴(kuò)張中。在過去的五年中,DAU 從 1 億增長至 3.76 億。在 2021 年,快手的 DAU 已經(jīng)超過了 3 億。主要推薦場景也從早期的發(fā)現(xiàn)頁、關(guān)注頁和同城頁等幾個(gè)主要頁面,擴(kuò)展到了如今的上百個(gè)推薦場景,包括電商、直播、增長、海外及本地生活等等。
伴隨著業(yè)務(wù)的快速發(fā)展,研發(fā)團(tuán)隊(duì)從幾十人擴(kuò)大到了上千人。在這種背景下,業(yè)務(wù)方面產(chǎn)生了兩個(gè)主要訴求:第一個(gè)是希望快速搭建一個(gè)新的推薦場景;另一個(gè)是快速復(fù)制有效的策略。
2、問題
早期,為了滿足這兩個(gè)訴求,開發(fā)團(tuán)隊(duì)選擇復(fù)制已有功能的架構(gòu)代碼,以加速開發(fā)過程。然而,隨著場景數(shù)量的不斷增加,這種方式已難以接受。因此,從長遠(yuǎn)來看,快手需要重新審視并優(yōu)化現(xiàn)有的代碼架構(gòu),以確保其能夠適應(yīng)未來的發(fā)展需求。
同時(shí),這種做法還會(huì)增加整個(gè)架構(gòu)的維護(hù)難度。在快手,架構(gòu)和算法人員配比較低,導(dǎo)致架構(gòu)工程師壓力較大。在線系統(tǒng)所有代碼都是用 C++ 語言編寫的,隨著算法團(tuán)隊(duì)人數(shù)的增加,系統(tǒng)越來越復(fù)雜,對線下代碼質(zhì)量的把控變得更加困難。經(jīng)常因?yàn)榇a bug 導(dǎo)致線上穩(wěn)定性問題。
另外,工程團(tuán)隊(duì)和算法團(tuán)隊(duì)之間存在天然的目標(biāo)差異。例如,算法團(tuán)隊(duì)追求快速迭代和實(shí)驗(yàn)上線,而工程團(tuán)隊(duì)更看重系統(tǒng)維護(hù)成本。因此,快手需要平衡兩個(gè)團(tuán)隊(duì)的需求和目標(biāo),以確保整個(gè)系統(tǒng)的穩(wěn)定性和可維護(hù)性。
另一種嚴(yán)重的情況是,項(xiàng)目的整個(gè)算法和工程代碼寫在同一個(gè)工作空間中,導(dǎo)致代碼存在嚴(yán)重的耦合現(xiàn)象,就像 DNA 雙鏈結(jié)構(gòu),彼此相互支撐,又相互糾纏在一起。這就意味著雙方都可能對對方產(chǎn)生一些意外的影響。
在這樣一個(gè)模式下,工程團(tuán)隊(duì)往往會(huì)陷入循環(huán)重構(gòu)的怪圈。隨著系統(tǒng)迭代時(shí)間的不斷增長,整個(gè)系統(tǒng)的復(fù)雜度也逐漸提高。當(dāng)達(dá)到一定閾值時(shí),工程團(tuán)隊(duì)需要投入大量人力進(jìn)行系統(tǒng)的重構(gòu)。重構(gòu)完成后,系統(tǒng)的復(fù)雜度會(huì)降低到一定水平,但隨著時(shí)間的推移,經(jīng)過一兩年的迭代,系統(tǒng)又會(huì)變得復(fù)雜起來,需要再次重構(gòu)。這種周而復(fù)始的現(xiàn)象每 1~2 年就會(huì)發(fā)生一次。
每次進(jìn)行這樣的大型重構(gòu),對工程團(tuán)隊(duì)的消耗非常大,導(dǎo)致團(tuán)隊(duì)成員很難集中精力去關(guān)注其它更有價(jià)值的架構(gòu)升級。因此,如何打破這個(gè)循環(huán)重構(gòu)的宿命就成為了一個(gè)急需解決的關(guān)鍵問題。
經(jīng)過深入分析,團(tuán)隊(duì)發(fā)現(xiàn)了問題的核心原因是業(yè)務(wù)代碼和架構(gòu)代碼之間存在過度的耦合。為了解決這個(gè)問題,快手自主研發(fā)了一套策略引擎框架。下面將詳細(xì)介紹該框架是如何解決這些問題的。
二、Dragonfly 框架介紹
1、Dragonfly 是什么
Dragonfly 在定位上是一個(gè)面向搜廣推領(lǐng)域的通用圖引擎框架及其周邊工具所構(gòu)建的開發(fā)生態(tài)。該系統(tǒng)為快手內(nèi)部搜廣推服務(wù)提供了統(tǒng)一的基座引擎,同時(shí)為上層業(yè)務(wù)提供了靈活的流程編排能力。
在底層,內(nèi)置了一些高效的數(shù)據(jù)模型,并提供了豐富的周邊工具。上圖展示了整個(gè)架構(gòu),最上層是各個(gè)搜廣推領(lǐng)域的策略引擎,下面是支持策略服務(wù)、召回服務(wù)、粗排精排服務(wù)的核心層,最底下是圖調(diào)度引擎。通過DSL算子編排,成功地將算法的開發(fā)模式從 C++ 為主轉(zhuǎn)變?yōu)橐?Python 為主。
2、策略編排
上圖中展示了一段代碼示例,以 Dragonfly 編寫策略的方式呈現(xiàn),非常直觀。代碼定義了一個(gè) flow 流程對象,類似于工作流的概念。在這個(gè) flow 中,提供了很多方法,每個(gè)方法背后都有一個(gè)相應(yīng)的算子。通過腳本,可以很容易理解這個(gè)流程。前兩個(gè)方法是兩步召回,從索引和服務(wù)中做召回,之后進(jìn)行去重、曝光、過濾等。再根據(jù) dislike 特征進(jìn)行過濾截?cái)唷=又M(jìn)入下一個(gè)階段,進(jìn)行多樣性的打散,然后進(jìn)行截?cái)嗖⒎祷亍?/span>
通過 Python 的 DSL 描述,算法同學(xué)可以不編寫 C++ 代碼,而是通過 Python 腳本簡單、直觀地描述一段策略流程,這個(gè) DSL 腳本將被編譯成一個(gè) Json 文件,交給線上的 C++ 服務(wù)運(yùn)行。這樣既享受了 Python 編寫邏輯的便利性,也沒有犧牲線上的性能。
為了實(shí)現(xiàn)這個(gè)效果,我們做了兩個(gè)核心的抽象:流程抽象和數(shù)據(jù)抽象。
3、流程抽象
利用算子化的方法加上 DAG 來拆分和抽象整個(gè)業(yè)務(wù)功能為各個(gè)算子。這些算子包括一些通用的算子,如過濾、召回、模型預(yù)估等。這些算子基本上由架構(gòu)編寫和維護(hù),各個(gè)業(yè)務(wù)可以直接復(fù)用,無需重復(fù)編寫。
通過自定義算子來滿足一些通用算子無法滿足的定制化的業(yè)務(wù)邏輯。這些自定義算子可以由業(yè)務(wù)人員自行編寫,以實(shí)現(xiàn)高度靈活的需求。
通過使用先前展示的 Python DSL,開發(fā)人員可以輕松編排這些算子。并且,由于這個(gè)腳本本質(zhì)上是一段 Python 代碼,因此可以在此基礎(chǔ)上利用 Python 自身語法能力實(shí)現(xiàn)更復(fù)雜的代碼拆分及模塊化管理等功能。
整個(gè) DAG 構(gòu)圖方式是基于數(shù)據(jù)驅(qū)動(dòng)的隱式構(gòu)圖,因此,所有的算子都可以做到全流程漂移。
如圖所示,假設(shè)我們有一個(gè)包含六個(gè)算子的 flow,其中 B、C、D 三個(gè)是異步的算子,它們分別有下游依賴 E 和 F。根據(jù)數(shù)據(jù)依賴關(guān)系和拓?fù)湫颍梢晕ㄒ坏胤赐瞥鲆环?DAG 圖,其中 B、C 是并行的關(guān)系,B、C、E 整體與 D 也是并行的關(guān)系。因此,整個(gè)流程的處理結(jié)構(gòu)就像上圖中部所示。
通過這樣的構(gòu)圖機(jī)制,理論上可以構(gòu)建出任意復(fù)雜的業(yè)務(wù)邏輯和業(yè)務(wù)流程。這里提到的可全程漂移意味著,如果將各個(gè)方法隨意換位置,那么構(gòu)圖的結(jié)構(gòu)也會(huì)自動(dòng)發(fā)生變化。
最后,整個(gè)流程的調(diào)度是一個(gè)全程無鎖的設(shè)計(jì),以支持在線的高并發(fā)需求。
4、數(shù)據(jù)抽象
除了流程抽象,Dragonfly 具備的另一項(xiàng)重要抽象能力是對數(shù)據(jù)的抽象。它提供了一種高性能的數(shù)據(jù)結(jié)構(gòu),叫做 DataFrame 表結(jié)構(gòu),類似于大數(shù)據(jù)領(lǐng)域中列存表的概念。
從邏輯上看,DataFrame 表結(jié)構(gòu)就像圖示的二維數(shù)據(jù)表,以 item 側(cè)的數(shù)據(jù)為例,每行代表一個(gè) Item,每列代表其屬性或特征。Common 側(cè)的數(shù)據(jù)實(shí)際上也是類似的,但因?yàn)?common 的數(shù)據(jù)對于所有item都是共享的,所以作為底層使用一個(gè)特化單行的 DataFrame 結(jié)構(gòu)去承載。通過這樣的 DataFrame 結(jié)構(gòu),可以比較容易地實(shí)現(xiàn)統(tǒng)一數(shù)據(jù)接口的能力。例如,Dragonfly 架構(gòu)為上層提供的是一個(gè)簡單的鍵值化數(shù)據(jù)接口,如果一個(gè) item 想訪問一個(gè)特征的值,只需要傳入 item 的 key(一般是 item _id) 和 like 這個(gè)名字,就能獲取到這個(gè)值。Schema Free 的特點(diǎn)確保了在線系統(tǒng)不需要因?yàn)樘砑有碌奶卣骰驍?shù)據(jù)而頻繁重新編譯,這比 protobuf 更加易用和高效。
此外,Dragonfly 框架對結(jié)構(gòu)進(jìn)行了諸多性能優(yōu)化,例如零拷貝技術(shù),這種技術(shù)貫穿于索引數(shù)據(jù)以及DataFrame間的數(shù)據(jù)傳遞等各個(gè)方面。
Dragonfly 框架更高級的功能是對邏輯表的全面支持。在復(fù)雜的業(yè)務(wù)場景中,可能需要處理一張大型物理表,每個(gè)團(tuán)隊(duì)只需要專注于其中的一部分流程。因此,可以基于底層物理表創(chuàng)建邏輯表,這一概念類似于數(shù)據(jù)庫中的視圖。與視圖的只讀不同,Dragonfly 架構(gòu)創(chuàng)建的邏輯表具有可讀寫性,可以作為其他團(tuán)隊(duì)劃分?jǐn)?shù)據(jù)操作空間的參考。通過這種方式,整個(gè)團(tuán)隊(duì)可以更清晰、更靈活地管理其數(shù)據(jù)操作空間。
通過統(tǒng)一數(shù)據(jù)接口,我們得以輕松地進(jìn)行數(shù)據(jù)讀寫管控,可以輕易地梳理并監(jiān)控在線數(shù)據(jù)的讀寫使用情況,包括是否存在不合規(guī)的數(shù)據(jù)使用。整個(gè)框架內(nèi)置了安全保障機(jī)制,確保了數(shù)據(jù)的并發(fā)安全。
5、DSL 層提供高階抽象能力
前面介紹的是框架底層的核心能力,但用戶主要會(huì)感知到的是 DSL 這一層。Dragonfly 提供了一些更高階的抽象能力,如標(biāo)準(zhǔn)算子的封裝,用戶可以直接使用。對于用戶來說,同步或異步是無感的,只需要簡單地調(diào)用算子接口,無需關(guān)心底層是同步還是異步實(shí)現(xiàn)。
此外,Dragonfly 在底層提供了分支流程控制、數(shù)據(jù)并行計(jì)算等高階功能。如上圖展示了數(shù)據(jù)并行計(jì)算的示例,假設(shè)要計(jì)算某個(gè)分?jǐn)?shù),類型為 double,如果每個(gè)計(jì)算的分?jǐn)?shù)需要一毫秒,那么 8 個(gè)串行計(jì)算就需要 8 毫秒。但是,實(shí)際上每個(gè)分?jǐn)?shù)的計(jì)算都是獨(dú)立的,可以將其視為數(shù)據(jù)上的并行操作。通過框架提供的 @ parallel 裝飾器,可以指定參數(shù)將數(shù)據(jù)分片,每片包含 4 個(gè) item,每個(gè)線程處理一片數(shù)據(jù),實(shí)現(xiàn)并行操作,將 8 毫秒降低到 4 毫秒。原理上跟向量化加速是一樣的。
對于流程,Dragonfly 提供了@async裝飾器幫助將子流程異步化,還提供了模塊化組件幫助上層 DSL 構(gòu)建更復(fù)雜的業(yè)務(wù)邏輯。與傳統(tǒng)的 C++ 代碼實(shí)現(xiàn)相比,使用 Dragonfly 的 DSL 只需要簡單地添加裝飾器即可實(shí)現(xiàn)諸多復(fù)雜的功能。
6、分層解耦
通過 Dragonfly Python DSL 我們將整個(gè)算法和架構(gòu)的研發(fā)工作空間進(jìn)行劃分和隔離,實(shí)現(xiàn)層次分明。在 DSL 之上是算法的工作空間,算法人員只需要編寫DSL編排算子并提交配置,而無需關(guān)心底層算子的實(shí)現(xiàn)。在 DSL 之下是架構(gòu)的工作空間,架構(gòu)人員只需要編寫算子,并提供二進(jìn)制文件以運(yùn)行配置。架構(gòu)對于上層業(yè)務(wù)邏輯無需關(guān)心。這樣就實(shí)現(xiàn)了清晰的層次劃分,使得兩者之間不會(huì)產(chǎn)生強(qiáng)烈的耦合效應(yīng),避免了互相干擾的情況。
7、應(yīng)用現(xiàn)狀
當(dāng)前,Dragonfly 已經(jīng)支撐了整個(gè)搜推廣領(lǐng)域的上千個(gè)在離線服務(wù)的運(yùn)行,實(shí)現(xiàn)了覆蓋整個(gè)推薦在線核心鏈路的技術(shù)模式。如圖,應(yīng)用范圍不僅覆蓋策略服務(wù),還包括整個(gè)鏈路上的召回服務(wù)、粗排精排重排等服務(wù)。
通過采用這一套技術(shù)模式,實(shí)現(xiàn)了幾個(gè)重要的目標(biāo)。首先,統(tǒng)一的技術(shù)模型實(shí)現(xiàn)了整個(gè)在線服務(wù)協(xié)議。這個(gè)技術(shù)模型也為我們提供了便利的監(jiān)控條件,可以輕松監(jiān)控整個(gè)鏈路每個(gè)服務(wù)的內(nèi)部算子情況、CPU 消耗等系統(tǒng)資源指標(biāo)。此外,一些底層優(yōu)化和編譯器優(yōu)化也可以通過一次開發(fā),在所有服務(wù)中復(fù)用。
當(dāng)所有服務(wù)都采用這一套模式時(shí),全鏈路將呈現(xiàn)一個(gè)靈活的狀態(tài)。這意味著鏈路節(jié)點(diǎn)上的每個(gè)節(jié)點(diǎn)都可以靈活地切分和融合。如果某個(gè)節(jié)點(diǎn)的服務(wù)隨著業(yè)務(wù)迭代時(shí)間的延長而變得臃腫,導(dǎo)致單機(jī)資源無法承受,可以將其從大單體服務(wù)切分為兩個(gè)小單體服務(wù)。同樣,如果發(fā)現(xiàn)某些服務(wù)對單機(jī)的資源消耗過低,可以將上下游的兩個(gè)服務(wù)進(jìn)行靈活融合,將其變?yōu)橐粋€(gè)服務(wù)。這種靈活的架構(gòu)可以像微架構(gòu)一樣,使我們能夠靈活地調(diào)整整個(gè)鏈路的架構(gòu),包括新舊服務(wù)的遷移。根據(jù)遷移經(jīng)驗(yàn),采用這一套技術(shù)模式可以使原有服務(wù)的 C++ 代碼量減少 50~80%,顯著降低了代碼的復(fù)雜性和線上穩(wěn)定性安全風(fēng)險(xiǎn)。
三、生態(tài)建設(shè)
1、生態(tài)工具
為了讓業(yè)務(wù)團(tuán)隊(duì)高效地使用這個(gè)框架,僅僅做好一個(gè)框架是遠(yuǎn)遠(yuǎn)不夠的。要讓用戶充分體驗(yàn)到這個(gè)框架的優(yōu)勢,需要構(gòu)建一個(gè)龐大的生態(tài)系統(tǒng)工具。
上圖展示了目前提供的相關(guān)工具。這些工具覆蓋了整個(gè)策略研發(fā)的全流程,包括上線前的編碼輔助、功能調(diào)試,以及上線后的指標(biāo)監(jiān)控和報(bào)警分析。這套框架的最大優(yōu)勢在于,所有這些生態(tài)工具都可以做到一次建設(shè)全業(yè)務(wù)復(fù)用。接下來介紹幾個(gè)重點(diǎn)工具。
2、Playground
這是網(wǎng)頁版調(diào)試工具,用戶可以在頁面上直接編寫 DSL,并通過網(wǎng)頁運(yùn)行查看結(jié)果。通過這個(gè)網(wǎng)頁版工具,用戶可以實(shí)現(xiàn)零部署的在線編寫調(diào)試。秒級響應(yīng),用戶可以在 Python 代碼中簡單構(gòu)造輸入輸出數(shù)據(jù),并執(zhí)行查看效果。用戶除了可以直接查看結(jié)果,也可以通過 Python print 查看流程中的特征數(shù)據(jù),或查看底層 C++ 算子的 glog 日志。這樣可以幫助用戶方便地調(diào)試程序邏輯。
3、白盒化回查
針對已經(jīng)上線的在線服務(wù),如果出現(xiàn)不良情況需要調(diào)查,整個(gè)框架具備自動(dòng)打點(diǎn)的功能。通過用戶 ID(uid),可以追蹤歷史記錄中某條請求的完整執(zhí)行情況;可以了解到該請求經(jīng)過了哪些算子,每個(gè)算子的耗時(shí)和輸出數(shù)據(jù)等詳細(xì)信息。通過這種方式,開發(fā)人員可以進(jìn)行歷史追蹤,排查可能出現(xiàn)的問題。
4、可視化
通過這種方式,可以從上至下、由粗到細(xì)地展示業(yè)務(wù)流程,能夠更清晰、直觀地了解整個(gè)業(yè)務(wù)流程的概況。
5、代碼治理
許多開發(fā)團(tuán)隊(duì)都面臨著算法代碼無限膨脹的問題,需要一個(gè)有效的預(yù)防機(jī)制。Dragonfly 框架可以自動(dòng)監(jiān)測在線運(yùn)行的無用算子并進(jìn)行召回,甚至可以識(shí)別無用的分支。這樣,系統(tǒng)可以定期生成報(bào)告,比如右側(cè)的按分支生成的報(bào)告。這個(gè)報(bào)告可以精確地定位到哪位作者在哪個(gè)文件、哪個(gè)函數(shù)中寫了哪個(gè)無用的分支,以及它已經(jīng)有多少天沒有被使用過了。
有了這樣的報(bào)告,就可以直接定位到編寫無用代碼的人,將報(bào)告發(fā)送給相關(guān)作者,促使其進(jìn)行深入剖析并刪除這些無用的代碼。這樣,可以有效防止代碼無限膨脹,避免給未來的系統(tǒng)精簡和重構(gòu)帶來不必要的壓力和消耗。
四、規(guī)劃展望
展望整個(gè)框架,未來將在以下三個(gè)方面持續(xù)發(fā)力:
1、性能方面
正在進(jìn)行中的工作是提供 numa-aware 的能力。新一代 CPU 架構(gòu)正在轉(zhuǎn)向多 numa 的架構(gòu),這可能讓已有服務(wù)的性能未處于最佳狀態(tài)。為了充分發(fā)揮硬件性能,需要上層代碼能夠更深入地感知 CPU 架構(gòu)。目前框架可以幫助上層算子更簡單的感知到 numa 架構(gòu)的情況,并靈活控制內(nèi)存分配策略,以實(shí)現(xiàn)更優(yōu)的訪存性能。
此外還可以根據(jù)整個(gè)鏈路關(guān)系執(zhí)行圖優(yōu)化,以降低線上服務(wù)耗時(shí),并將這種優(yōu)化擴(kuò)展到全鏈路。
2、管控力方面
得益于全鏈路統(tǒng)一基座引擎的支持,可以輕松實(shí)現(xiàn)全鏈路特征管理和數(shù)據(jù)血源追蹤。未來,系統(tǒng)將能夠自動(dòng)檢測出哪些數(shù)據(jù)已無用并直接將其刪除。
同時(shí)我們將建設(shè)系統(tǒng)的自凈化能力,實(shí)現(xiàn)代碼治理的自動(dòng)化。系統(tǒng)將能夠識(shí)別出無用的邏輯或低效代碼,并從代碼庫中定期自動(dòng)刪除,從而持續(xù)保證系統(tǒng)的健壯性。
3、產(chǎn)品化方面
希望在未來加強(qiáng)整個(gè)生態(tài)工具鏈的建設(shè),提供更智能的工具,用 AI 技術(shù)驅(qū)動(dòng)更高效的研發(fā)流程。
系統(tǒng)也將致力于提供更完整的綜合解決方案,甚至提供 to B 的能力。
如果您對此領(lǐng)域感興趣并希望加入我們的行列,共同創(chuàng)造卓越的成果,請將簡歷發(fā)送至郵箱 fangjianbing@kuaishou.com。我們將一起致力于構(gòu)建更強(qiáng)大、更智能的工具和服務(wù)。謝謝大家的參與和支持!
五、問答環(huán)節(jié)
Q1:Dragonfly 的自定義算子的表達(dá)能力是否會(huì)比較有限,或者說它是否總能翻譯成 C++,還是能夠覆蓋一些比較復(fù)雜的 C++ 的推薦邏輯。
A1:取決于對算子抽象的程度。因?yàn)檫@個(gè)算子并不是直接翻譯成 C++ 代碼,而是由 C++ 代碼組裝起來。比如要做一個(gè)過濾,需要首先把過濾相關(guān)的邏輯先抽象出來,有哪些是公用的,哪些是可以配置化的,抽象出一個(gè)過濾的核心邏輯,給大家復(fù)用,而并不是直接在 Python 里面寫一個(gè)很細(xì)致很具體的過濾代碼,然后把它翻譯過來。算子并不是細(xì)到代碼行級別的粒度。
Q2:自定義算子的拆分粒度是什么?在實(shí)際開發(fā)中是否屬于自定義算子,是工程側(cè)還是算法側(cè)的同學(xué)去決定這件事情。
A2:這件事一般會(huì)是算法側(cè)自己去開發(fā),工程側(cè)一般會(huì)去開發(fā)一些通用性的算子。自定義算子這部分會(huì)存在一些現(xiàn)實(shí)的問題,比如不同算法同學(xué)的抽象能力以及代碼能力是不一樣的,他們對自定義算子的粒度把控以及設(shè)計(jì)可能是存在欠缺的,會(huì)導(dǎo)致自定義算子的復(fù)用性很有限。
Q3:第三個(gè)問題是關(guān)于控制流的,和 TensorFlow 的圖的本質(zhì)區(qū)別是什么?控制流具體是如何實(shí)現(xiàn)的?
A3:概念上類似于 TensorFlow,也是數(shù)據(jù)驅(qū)動(dòng)的構(gòu)圖方式。TensorFlow 直接暴露成一個(gè)變量,通過變量的傳遞就能推斷出數(shù)據(jù)依賴關(guān)系。但數(shù)據(jù)在我們 DSL 中是一個(gè)隱藏的概念,比如文中的例子,類似 ctr、pctr 這樣的數(shù)據(jù),它算是作為一個(gè)配置項(xiàng),體現(xiàn)在某一個(gè)算子的配置里面。從代碼級別上來看,并沒有存在這么一個(gè) pctr 的 python 變量去承接這個(gè)數(shù)據(jù),而是隱藏在 DSL 之下的一個(gè)概念,因?yàn)閿?shù)據(jù)關(guān)系非常復(fù)雜,很難用變量傳遞去表達(dá)清晰。這是與 TensorFlow 的一個(gè)區(qū)別。TensorFlow 是通過參數(shù)傳遞的方式進(jìn)行數(shù)據(jù)傳遞,而我們的控制流是通過函數(shù)的配置,它的入?yún)⒂幸粋€(gè)叫 pctr 的字面量值,后續(xù)某一個(gè)算子有一個(gè) pctr 的值作為它配置的輸入,這樣去判斷出它的前后依賴關(guān)系,所以整個(gè)邏輯也都是靠拓?fù)浼訑?shù)據(jù)依賴的方式去構(gòu)圖??傊砩项愃?,但具體實(shí)現(xiàn)細(xì)節(jié)上不太一樣。
Q4:關(guān)于微服務(wù)劃分,Dragonfly 實(shí)現(xiàn)的文件是一個(gè)微服務(wù),想了解一下 DSL 中的算子的組織和微服務(wù)的劃分有什么樣的關(guān)系?
A4:一個(gè) DSL 實(shí)際上最終對應(yīng)的是一個(gè)服務(wù)的配置,比如策略服務(wù),最終會(huì)生成一個(gè) Json 的配置,然后交給系統(tǒng)去部署運(yùn)行起來,對應(yīng)的下游的召回粗排精排重排,也分別有一個(gè)獨(dú)立的配置。等同于一個(gè) DSL 對應(yīng)一個(gè)線上的服務(wù)節(jié)點(diǎn)。如果要做節(jié)點(diǎn)拆分,實(shí)際上就是把 DSL 前半部分的方法調(diào)用摘出來,把它挪到另外一個(gè) DSL 的文件里面。