從資源彈性到數據彈性,乾象如何將雲上量化研究效率提升 40%?

機器學習、雲計算、雲原生等技術的進步給金融行業創新注入了新的動力,以乾象投資 Metabit Trading 爲代表的以人工智能爲核心的科技型量化投資公司的工作就非常有代表性。他們通過深度融合和改進機器學習算法,並將其應用於信噪比極低的金融數據中,爲投資人創造長期可持續的回報。

與傳統的量化分析不同,機器學習不僅關注股價、交易量和歷史回報率等結構化數據,還注入來自研報、財報、新聞和社交媒體等非結構化數據來深入瞭解證券價格走勢和波動性。然而,將機器學習應用於量化研究是具有挑戰性的,因爲原始數據可能包含噪聲。此外,他們還需要應對許多挑戰,如突發任務、高併發數據訪問和計算資源限制等。

爲此,乾象投資在研發投入、創新支持和基礎平臺建設方面持續發力。他們的研究基礎設施團隊構建了一個高效、安全、規模化的工具鏈研發流程,通過合理利用雲計算和開源技術突破了單機研發的限制。本文將分享乾象量化研究基礎平臺的具體實踐,介紹基於 Fluid+JuiceFSRuntime 的公共雲彈性量化投研工作支撐。

量化研究的工作詳解

作爲 AI-powered hedge fund,通過 AI 模型訓練進行策略研究是我們最主要的研究方式。首先,在模型訓練之前需要對原始數據做特徵提取。金融數據的信噪比特別低,如果直接使用原始的數據進行訓練,得到的模型噪音會非常大。原始數據除了行情數據,即大家經常會看到的市場上的股價、交易量之類的數據,也包括一些非量價的數據,比如研報、財報、新聞、社交媒體等之類的非結構化數據,研究人員會通過一系列的變換提取出特徵,再進行 AI 模型訓練。可以參考下面我們研究場景中和機器學習關聯最緊密的策略研究模式的簡化示意圖。

模型訓練會產出模型以及信號。信號是對未來價格趨勢的判斷,信號的強度意味着策略導向性的強度。量化研究員會根據這些信息去優化投資組合,從而形成交易的實時倉位。這個過程中會考慮橫向維度(股票)的信息來進行風險控制,例如某一行業的股票不要過度持倉。當倉位策略形成之後,量化研究員會去模擬下單,而後得到實時倉位對應的盈虧信息,從而瞭解到這個策略的收益表現,這就是一個量化研究的完整流程。02

量化研究基礎平臺的需求

第一,突發任務多,彈性要求高。在策略研究的過程中,量化研究員會產生策略想法,並會通過實驗去驗證自己的想法。伴隨着研究人員新想法的出現,計算平臺就會產生大量的突發任務,因此我們對計算的彈性伸縮能力要求很高。

上圖是我們某個集羣一段時間的運行實例數據。以上圖爲例,可以看到在多個時間段裏,整個集羣實例數高峯時刻可以達到上千個,但是同時整個計算集羣的規模也會有縮容到 0 時候。量化機構的計算任務和研究員的研發進度是有很大關聯的,波峯波谷的差距會非常大,這也是離線研究任務的特點。

第二,熱數據高併發訪問,除了計算需要彈性,數據緩存也需要彈性。對於熱數據,比如行情數據,通常會有上百個任務同時訪問數據,它的吞吐要求非常高,峯值時數百 Gbps 甚至 Tbps 級別的聚合帶寬才能滿足需求。但是當計算集羣中沒有任何節點的時候,此時的吞吐需求爲 0,如果是剛性吞吐這就需要彈性吞吐擴縮容的能力。

第三,容量和吞吐的獨立線性擴展能力,對金融模型訓練非常重要。傳統分佈式存儲帶寬與吞吐僅和數據使用容量成正比,而量化研究過程中會創建大量的容器併發訪問存儲系統的數據,會觸發存儲系統訪問限流。這就造成計算資源極致彈性與存儲系統有限帶寬之間的矛盾。而量化研究的數據量其實不是特別大,很多市場的量價數據總量也不會超過 TB 級,但是數據訪問需要的峯值吞吐卻非常高。

第四,數據親和性調度,同一數據源多次運行訪問本地緩存可以被複用。充分發揮熱點數據集的緩存節點優勢,在對用戶無感知的前提下,智能的將任務調度到數據緩存節點上。讓常用的模型訓練程序越來越快。

第五,IP保護:數據共享與數據隔離。出於 IP 保護的需求,不僅在計算任務上需要做隔離,在數據上也是需要具備權限控制的隔離能力;同時對行情數據這類相對公開的數據,還需要支持研究員的獲取方式是便捷的。

第六,緩存中間結果。計算任務模塊化的場景會對中間結果的存儲跟傳輸也有需求。舉個簡單的例子,在特徵計算過程中會生成比較大量的特徵數據,這些數據會立刻用於接下來大規模高併發的訓練節點上。顯而易見在這種場景下我們需要一個高吞吐和高穩定的中間緩存做數據傳遞。

第七,多文件系統的支持。計算任務中各類型的任務會對應的各種特性的數據類型和使用方式,因而我們不同團隊會採用不同的文件系統包括 OSS,CPFS,NAS,JuiceFS,以獲取在各自情況下的性能最優化。Fluid 的不同 runtime 能夠靈活的支持文件系統與任務的組合,使得任務計算能夠在 K8s 上更高效合理的利用對應資源避免不必要的浪費。

Fluid+JuiceFSRuntime:爲雲上量化研究基礎平臺提供高效支撐

出於 POSIX 兼容,成本,高吞吐的考慮,我們選擇了 JuiceFS 雲服務作爲分佈式底層存儲。選擇了 JuiceFS,發現現有 Kubernetes 的 CSI 體系並不能很好地支持我們對數據訪問性能、彈性吞吐能力以及數據共享隔離的需求,具體來看:

1. 傳統的 Persistent Volume Claim 是面向通用存儲的抽象,缺乏對同一個存儲複雜數據訪問模式協同良好的支持:在不同的應用場景下,應用對同一存儲中不同文件的使用方式不同,比如我們多數併發計算任務要求只讀;但是也有 Pipeline 數據中轉,數據特徵生成之後,需要中轉到模型訓練中,此時就要求讀寫;這導致了很難在同一個 PVC 中統一設置元數據更新和緩存策略。實際上,這些策略應該完全取決於應用使用數據的模式。

2. 數據隔離與共享:不同數據科學家團隊訪問不同的數據集需要天然隔離,並且要求比較容易管理;同時支持公共數據集訪問共享,特別是緩存數據共享,由於行情數據這類相對公開的數據,不同的研究員團隊會反覆使用,希望獲得“一次預熱、全公司收益”的效果。

3. 數據緩存感知的 Kubernetes 調度:相同模型、相同輸入、不同的超參的作業以及微調模型、相同輸入的作業都會不斷重複訪問同一數據,產生可以複用的數據緩存。但是原生的 Kubernetes 調度器無法感知緩存,導致應用調度的結果不佳、緩存無法重用,性能得不到提升。

4. 數據訪問吞吐可以彈性擴容到數百 Gbps:傳統的高性能分佈式文件存儲,一般的規格是 200 MB/s/TiB 基線的存儲規格,其最大 IO 帶寬是 20Gbps,而我們任務的峯值 IO 帶寬需求至少需要數百 Gbps,顯然無法滿足我們的要求。

5. 數據緩存的成本最優:由於公共雲提供了計算資源極致彈性,可以短時間內彈出幾百甚至上千計算實例,而當這些計算資源同時訪問存儲時,在高峯時吞吐需要數百 Gbps 甚至更高,此時需要通過計算中的緩存集羣去服務熱數據。但是很多時間段內,計算集羣會縮容爲 0,此時維護一個很大的緩存集羣就得不償失了。我們更傾向於在使用之前進行數據預熱,同時根據業務的運行規律執行定時擴縮容;而當計算集羣沒有作業在運行,再縮容到默認緩存節點,從而達到對數據緩存吞吐的動態彈性伸縮控制。

爲了達到上述目標,我們迫切希望找到 Kubernetes 上具有彈性分佈式緩存加速能力同時很好支持 JuiceFS 存儲的軟件。我們發現 CNCF Sandbox 項目 Fluid[1] 和 JuiceFS 存儲有很好的協同,JuiceFS 團隊正好也是 Fluid 項目中 JuiceFSRuntime 的主要貢獻者和維護者。於是,我們設計了基於 Fluid 的架構方案並選擇了原生的 JuiceFSRuntime。

架構組件介紹

Fluid

Fluid 不同於傳統的面向存儲的 PVC 抽象方式,而是在 Kubernetes 上針對“計算任務使用數據”的過程進行抽象。它提出了彈性數據集 Dataset 的概念,以應用對數據訪問的需求爲中心,給數據賦予特徵,如小文件、只讀、可讀寫等;同時將數據從存儲中提取出來,並且給有特徵的數據賦予範圍,如用戶只關心某幾天的數據。圍繞 Dataset 構建調度系統,關注數據本身和使用數據的應用的編排,強調彈性和生命週期管理。

JuiceFSRuntime

JuiceFSRuntime 基於 JuiceFS 的分佈式緩存加速引擎, 通過將數據分佈式緩存技術與Fluid自動彈性伸縮(Autoscaling)、可遷移(Portability)、可觀測(Observability)、親和性調度(Scheduling)能力相結合,支持場景化的數據緩存和加速能力。在Fluid上使用和部署 JuiceFSRuntime 流程簡單、兼容原生 Kubernetes 環境、可以開箱即用,並深度結合 JuiceFS 存儲特性,針對特定場景優化數據訪問性能。

使用基於 JuiceFSRuntime 的 Fluid 的原因

1. Dataset 抽象滿足雲原生機器學習場景的性能優化和隔離共享等多樣需求:

  • 場景化性能調優:通過 Dataset 可以針對不同訪問特點的數據集作相應的優化,比如模型訓練場景通常是隻讀,而特徵計算需要讀寫。
  • 數據隔離:Dataset 天然的通過 Kubernetes 的命名空間這種資源隔離機制用來限制不同團隊對集羣中數據集的訪問權限,並且不同的數據集對應 JuiceFS 中不同的子目錄(JuiceFS 企業版還支持目錄配額),這可以滿足數據隔離的需求。
  • 數據緩存共享:對於一些不同團隊都會頻繁使用的公開數據集,Fluid 支持跨Kubernetes Namespace 的數據訪問,可以做到一次緩存,多個團隊共享,這也滿足了數據緩存共享的需求。

2. Runtime 場景化的計算資源優化:Dataset 是數據的通用抽象,而對於數據真正的操作,實際上由 JuiceFSRuntime 實現,所以 Runtime 的 CPU,Memory,網絡和緩存 Worker 數量等資源配置勢必會影響性能,這就需要針對 Dataset 的使用場景,對 Runtime 的計算資源進行優化配置。

3. 彈性分佈式緩存:支持豐富的擴縮容策略,包括手動伸縮、自動彈性伸縮和定時彈性伸縮,可以根據需要找到最優的彈性方案。

  • 手動伸縮:通過 Dataset 的可觀測性,可以瞭解數據集的數據量和緩存 Runtime 需要的緩存資源,也可以根據應用訪問的併發度設置 Runtime 的 Replicas 數量(緩存 Worker 的數量),不用的時候可以隨時縮容。
  • 自動彈性伸縮:根據數據指標進行自動彈性伸縮。比如根據數據緩存量和吞吐量等指標進行緩存彈性伸縮,可以制定當緩存百分比超過 80%,或者當客戶端數量超過一定閾值的時候進行自動擴容。
  • 定時彈性伸縮:根據業務特性設置定時彈性伸縮,可以實現無人蔘與的數據彈性擴縮容機制。

4. 自動的數據預熱:避免在訓練時刻併發拉取數據造成數據訪問競爭,還可以和彈性伸縮配合,避免過早的創建緩存資源。

5. 數據感知調度能力:在應用被調度時,Fluid 會通過 JuiceFSRuntime 把數據緩存位置作爲一個調度信息提供給 K8s 調度器,幫助應用調度到緩存節點或者離緩存更近的節點。整個過程對用戶透明,實現數據訪問性能的優勢最大化。

落地實踐

根據實踐,我們總結了以下經驗供大家參考。

在 Fluid 的 JuiceFSRuntime 選擇高網絡 IO 和大內存的 ECS 作爲緩存節點

隨着 ECS 網絡能力的不斷提升,當前網絡帶寬已經遠超 SSD 雲盤 IO 能力。以阿里雲上的 ecs.g7.8xlarge 規格的 ECS 爲例,其帶寬峯值爲 25Gbps,內存爲 128GiB。理論上,完成 40G 數據讀取僅需要 13s。我們的數據是存儲在 JuiceFS 上的,因此爲了實現大規模的數據讀取,我們需要首先將數據加載到計算所在 VPC 網絡中的計算節點中。以下爲我們使用的一個具體例子,爲了提高數據讀取速度,我們配置 cache 節點使其選擇使用內存來緩存數據。這裏需要注意:

  • Worker 主要負責分佈式數據緩存,爲了提高數據讀取速度,我們可以爲 Worker 配置內存性能相對較高的機型。而 Worker 的調度策略在 Dataset 中配置,因而需要在 Dataset 中爲 Worker 配置親和性策略。
  • 當任務沒有特定機型需求時,爲保證 Cluster 的 AutoScaler 能成功擴容,實踐中也建議在進行親和性配置時選擇多種實例類型以保證擴容/任務執行的成功。
  • Replicas 是初始的緩存 Worker 數量,後期可以通過手動觸發或自動彈性伸縮進行擴縮容。
  • 當指定 tieredstore 後,即無需在 Kubernetes 的 Pod 中設置 request 的內存,Fluid 可以自動處理。
  • 如在緩存節點上的 JuiceFS mount 有不同的配置,例如 cache size 大小, 掛載路徑等,可以通過 worker 裏的 options 進行覆蓋。
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: metabit-juice-research
spec:
  mounts:
    - name: metabit-juice-research
      mountPoint: juicefs:///
      options:
          metacache: ""
          cache-group: "research-groups"
      encryptOptions:
        - name: token
          valueFrom:
            secretKeyRef:
              name: juicefs-secret
              key: token
        - name: access-key
          valueFrom:
            secretKeyRef:
              name: juicefs-secret
              key: access-key
        - name: secret-key
          valueFrom:
            secretKeyRef:
              name: juicefs-secret
              key: secret-key
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
            - key: node.kubernetes.io/instance-type
              operator: In
              values:
                - ecs.g7.8xlarge
                - ecs.g7.16xlarge
  tolerations:
  -key: jfs_transmittion
  operator: Exists
  effect: NoSchedule
---
apiVersion: data.fluid.io/v1alpha1
kind: JuiceFSRuntime
metadata:
  name: metabit-juice-research
spec:
  replicas: 5
  tieredstore:
    levels:
      - mediumtype: MEM
        path: /dev/shm
        quota: 40960
        low: "0.1"
   worker:
     nodeSelector:
       nodeType: cacheNode
     options:
       cache-size: 409600
       free-space-ratio: "0.15“

配置自動彈性伸縮策略

受業務形態的影響,Metabit 在固定時段會有跟高的用量需求,因此簡單的配置定時緩存節點的彈性伸縮策略能到達到不錯的收益,例如對成本的控制,對性能提升。

apiVersion:

autoscaling.alibabacloud.com/v1beta1
kind: CronHorizontalPodAutoscaler
metadata:
  name: research-weekly
  namespace: default
spec:
   scaleTargetRef:
      apiVersion: data.fluid.io/v1alpha1
      kind: JuiceFSRuntime
      name: metabit-juice-research
   jobs:
   - name: "scale-down"
     schedule: "0 0 7 ? * 1"
     targetSize: 10
   - name: "scale-up"
     schedule: "0 0 18 ? * 5-6"
     targetSize: 20

更進一步,如果通過業務中具體的 metrics 如緩存比例閾值,IO throughput 等觸發帶有複雜自定義規則的彈性伸縮策略可以實現更爲靈活的緩存節點擴縮容配置以帶來更高和更穩定的性能表現。具體來講,在靈活度和性能層面會有以下一些優點:

  • 無需精準感知底層數據或擁有固定的擴縮容規則, 依據集羣狀態自適應的配置緩存副本上下限。
  • 階梯式擴容避免一開始就創建過多的 ECS,造成花費上的浪費。
  • 避免爆發式的 ECS 訪問 JuiceFS 數據造成帶寬搶佔。

觸發數據預熱

通過數據預熱提升緩存比例,進而觸發自動彈性伸縮;同時監控緩存比例,當緩存比例達到一定閾值同時開始觸發任務下發,避免過早下發高併發任務導致 IO 延遲。

鏡像預埋

由於 Metabit Trading 使用計算和數據彈性的規模很大,瞬間會彈出非常多的 Pod,這就會導致鏡像下載限流。網絡帶寬資源在 pod 拉起過程中是稀缺的,爲避免pod 創建時因拉取容器鏡像延時帶來的各種問題,我們建議對 ECS 的鏡像進行客製化改造,對需要的系統性鏡像做到“應埋盡埋”從而降低 pod 拉起的時間成本。具體例子可參考 ACK[2] 的基礎鏡像。

彈性吞吐提升帶來的性能和成本收益

在實際部署評估中,我們使用 20 個 ecs.g7.8xlarge 規格的 ECS 作爲 woker 結點構建 JuiceFSRuntime 集羣,單個 ECS 結點的帶寬上限爲 25Gbps;爲了提高數據讀取速度,我們選擇使用內存來緩存數據。

爲便於對比,我們統計了訪問耗時數據,並與使用 Fluid 方式訪問數據耗時進行了對比,數據如下圖所示:

可以看出,當同時啓動的 Pod 數量較少時,Fluid 與分佈式存儲相比並沒有明顯優勢;而當同時啓動的 Pod 越多時,Fluid 的加速優勢也越來越大;當同時併發擴大到 100 個 Pod 時,Fluid相比傳統分佈式存乎可以降低超過 40% 的平均耗時。這一方面提升了任務速度,另外一方面也確實的節省了 ECS 因爲 IO 延時帶來的成本。

更重要的是,因整個 Fluid 系統的數據讀取帶寬是與 JuiceFSRuntime 集羣規模正相關的,如果我們需要同時擴容更多的 Pod,則可以通過修改 JuiceFSRuntime 的 Replicas 來增加數據帶寬,這種動態擴容的能力是分佈式存儲目前無法滿足的。

展望

Metabit 在 Fluid 的實踐上走出了踏實的第一步,面對這個不斷創新和持續輸出的技術框架我們也在思考如何發揮在更多合適的場景發揮其完備的功能。這裏簡單聊聊我們的一些小觀察,拋磚引玉,供大家發揮。

1. Serverless 化能夠提供更好的彈性:目前我們通過自定義鏡像的方式提升應用容器和Fluid組件的彈性效率,我們也關注到在 ECI 上使用 Fluid 能更高效和簡單的應用擴展彈性,同時降低運維複雜度。這是一個在實踐中值得去探索的方向。

2. 任務彈性和數據緩存彈性的協同:業務系統瞭解一段時間內使用相同數據集的任務併發量,並且任務排隊的過程中執行數據預熱和彈性擴縮容;相應的當數據緩存或者數據訪問吞吐滿足一定條件,觸發排隊任務從等待變成可用。

總結和致謝

Metabit Trading 在生產環境使用 Fluid 已經接近一年半了,包括 JindoRuntime、JuiceFSRuntime 等,目前通過 JuiceFSRuntime 實現了高效的大規模量化研究。Fluid 很好的滿足了簡單易用、穩定可靠、多 Runtime、易維護以及讓量化研究員的使用感透明等好處。

Metabit Trading 的大規模實踐幫助我們團隊在使用公共雲上積累了很好的認知,在機器學習和大數據場景下,不但計算資源需要彈性,與之配合的數據訪問吞吐也需要與之相匹配的彈性,傳統的存儲側緩存由於成本,靈活,按需彈性的差異,已經很難滿足當前場景的需求,而 Fluid 的計算側彈性數據緩存的理念和實現則非常合適。

這裏要特別感謝 JuiceData 的朱唯唯,Fluid 社區的車漾,徐之浩和顧榮老師的持續支持。因爲有他們的維護,社區內有活躍的討論和快速的響應,這對我們的順利 adoption 起到了關鍵的作用。07

相關鏈接

[1] Fiuld

https://github.com/fluid-cloudnative/fluid

[2] ACK

https://www.aliyun.com/product/kubernetes?spm=5176.19720258.J_3207526240.33.1d2276f46jy6k6

作者介紹

李治昳,Metabit Trading - AI Platform Engineer,builder 、雲原生技術 learner,曾任Citadel高級工程師。

李健弘, Metabit Trading - Engineering manager of AI Platform,專注於在量化研究領域搭建機器學習平臺和高性能計算平臺,曾任 Facebook 高級工程師。

本文作者來自乾象投資 Metabit Trading,公司成立於2018年,是一家以人工智能爲核心的科技型量化投資公司。核心成員畢業於 Stanford、CMU、清北等知名高校。目前,管理規模已突破 50 億元人民幣, 並且在2022年市場中性策略收益排名中名列前茅,表現亮眼。

原文鏈接

本文爲阿里雲原創內容,未經允許不得轉載。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章