在前文中,我們描述了一個(gè)計(jì)算的算法結(jié)構(gòu)模型。接下來(lái),我們要設(shè)計(jì)這個(gè)計(jì)算的算法運(yùn)行時(shí)。在實(shí)踐中,對(duì)之前的算法結(jié)構(gòu)模型設(shè)計(jì)做了一些細(xì)微的調(diào)整,例如,無(wú)序的棧區(qū)被去除了,就地計(jì)算更加高效。另外,引入了Layout Template的概念,Calculation Context被用于組織算法運(yùn)行時(shí)。
在算法運(yùn)行時(shí),我們需要為本次計(jì)算開(kāi)辟一塊內(nèi)存空間。為了確保這塊內(nèi)存空間盡可能的小,需要一個(gè)新的結(jié)構(gòu)來(lái)容納必須的數(shù)據(jù)。這個(gè)結(jié)構(gòu)將不包括算法布局模板中的元數(shù)據(jù)信息,例如,指定一個(gè)算法布局以并行方式運(yùn)行,指定計(jì)算子的求值結(jié)果是否需要輸出,指定計(jì)算子求值結(jié)果的精度等。算法結(jié)構(gòu)中的各個(gè)模型實(shí)例可以通過(guò)引用來(lái)獲得元數(shù)據(jù)。
計(jì)算子的定位是另一個(gè)重要的概念。前文提到的場(chǎng)景表明,此類(lèi)計(jì)算中前后的計(jì)算子求值存在著相互依賴(lài)的關(guān)系。因此,我們引入了Item Location Map的概念,確保有一個(gè)快速的連接路徑來(lái)定位計(jì)算子的錨。下面是最終設(shè)計(jì)的算法運(yùn)行時(shí),見(jiàn)圖4。

值得一提的是,每一個(gè)計(jì)算布局都需要指定是否需要采用并行計(jì)算。這和實(shí)際的計(jì)算場(chǎng)景有關(guān),基于NQ模型,在某些場(chǎng)景下,并行計(jì)算所帶來(lái)的調(diào)度開(kāi)銷(xiāo)可能大于其帶來(lái)的好處,有興趣的朋友可以看看這篇文章。
更多的算法細(xì)節(jié)這里就不贅述了。下圖是最終求值的部分結(jié)果截圖,見(jiàn)圖5。我的E450筆記本計(jì)算耗時(shí)300ms左右,相信在40核的服務(wù)器上會(huì)有更好的表現(xiàn)。

正如前文所述,在企業(yè)應(yīng)用中,算法設(shè)計(jì)通常只是計(jì)算的一個(gè)組成部分。我們還需要考慮如何使用這個(gè)算法的計(jì)算框架,從而服務(wù)于各種計(jì)算場(chǎng)景。
一個(gè)好的計(jì)算框架,應(yīng)該具備良好的接口和簡(jiǎn)潔必要的輸入約束。單純從本文所提到的計(jì)算場(chǎng)景來(lái)看,最理想的工作方式是,使用者只需要描述計(jì)算布局,撰寫(xiě)各個(gè)計(jì)算子的公式,然后,計(jì)算框架進(jìn)行計(jì)算,為使用者提供計(jì)算結(jié)果。因此,我們通過(guò)json來(lái)定義計(jì)算布局,通過(guò)Groovy所提供的Closure來(lái)配置公式,見(jiàn)圖6。

關(guān)于框架設(shè)計(jì),我將在軟件架構(gòu)論中展開(kāi),這里也不在贅述。
注:我的同事Yi Feng指出,計(jì)算布局的基本想法和TensorFlow中所用的計(jì)算圖比較像,我因此去學(xué)習(xí)了一下,發(fā)現(xiàn)兩者都是從計(jì)算規(guī)則入手。不過(guò),計(jì)算圖顯然更加基礎(chǔ),適應(yīng)更多的計(jì)算需求,本文中的計(jì)算布局,其設(shè)計(jì)目的是為了解決并行計(jì)算的問(wèn)題,應(yīng)用范圍也沒(méi)有那么廣。謝謝Yi的指教。