深入瞭解Python的Dask分散式排程程式 - selectfrom
Dask 是一個強大的 Python 庫,可讓您使用一個程式碼將資料工程從一臺機器擴充套件到多臺機器,並具有 Python 的可擴充套件性。這種分散式電源的核心是 Dask 分散式排程程式。
從本質上講,Dask排程器將工作交給某個工作者worker。如果該工作者worker看起來已經飽和,並且在一段時間後無法啟動任務,Dask Scheduler就會將該工作拿走,並將其交給另一個工作者。
這方面的程式碼可以在dask.distributed>stealing.py中找到,你可以在GitHub.上進行跟蹤。
WorkStealing類保持對幾個work-stealing重要狀態的跟蹤:
- stealable_all:跟蹤計劃中的任務,並且是 "可偷的"。有一個 "級別 "的概念,預先設定了15個級別的可steal狀態,這有助於Scheduler決定需要重新分配工作的緊迫性。
- stealable:記錄我們可以steal工作的工人的情況。
- key_stealable:跟蹤當前被分配的工人,級別配對。
- saturated: 一個已經飽和的工人列表。
Dask分散式排程器是如何重新平衡任務負載的?
dask.distributed > stealing.py > WorkStealing > balance()
還記得飽和saturated列表嗎?我們取前10名飽和工人,並在其中找到那些分配的任務多於他們目前能處理的工人,其邏輯如下:
combined_occupancy(ws) > 0.2 and len(ws.processing) > ws.nthreads
Occupancy是一個雙數,用於跟蹤任務的中位執行時間,在某種意義上是一個啟發式的數值,用於預測要花多長時間。nThreads是我們通常的執行緒數。隨著工作者積累了更多的工作,飽和/閒置列表會保持最新,並且可以增加/減少長度。
我們現在引入級別和成本乘數的概念,以決定任務竊取優先權。我們有15個級別的任務,以及相應的成本乘數。
從現在開始(為了準確起見,總是參考原始碼),成本乘數看起來是這樣的,按照級別增加的順序。
[1, 1.03125, 1.0625, 1.125, 1.25, 1.5, 2, 3, 5, 9, 17, 33, 65, 129, 257]
對於每個級別,我們都會瀏覽所有可竊取的任務,並做一個成本效益分析。
dask.distributed > stealing.py > WorkStealing > balance > maybe_move_task
目前的決策演算法如下:
如果我們偷了任務,成本={閒置工人的佔用率+(成本乘數*任務所需的估計時間)}。
如果我們沒有偷竊,成本={飽和工人的佔用率-(任務所需的估計時間/2}。
occ_idl + cost_multiplier * duration <= occ_sat - duration / 2
我現在不確定為什麼要這樣定義,但我要猜測,有一些選擇是基於對時間的學習而做出的。
最後,我們轉向實際的偷竊任務 讓我們來看看重新分配任務的機制。
async def move_task_confirm
我們將偷竊方法稱為我們想要偷竊的任務。該方法在in_flight任務佇列中尋找該任務。然後檢查 "stimulus ID",這似乎是在檢查偷竊請求發出時任務的狀態。如果請求是陳舊的,終止。如果不是,繼續。
self.in_flight_occupancy[thief] -= d["thief_duration"]
self.in_flight_occupancy[victor]+= d["victor_duration"]
然後我們更新我們偷來並給了任務的工人的佔用率(預期平均任務完成時間保持在兩倍)。
ts.state != “processing” : abort steal
elif state in _WORKER_STATE_CONFIRM : only then we still
然後我們檢查工作者的狀態。如果受害者已經在執行,則中止偷竊。如果受害者仍未啟動該任務,則偷竊。
這似乎是work-stealer與Spark和Hadoop類系統的關鍵區別之一。
Spark和Hadoop有能力推測地安排同一任務的多次執行,以應對可能的 "滯後 "任務,而Dask目前沒有這樣做。
self.remove_key_from_stealable(ts) ts.processing_on = thief duration = victim.processing.pop(ts) victim.occupancy -= duration thief.processing[ts] = d[“thief_duration”] thief.occupancy += d[“thief_duration”] self.scheduler.total_occupancy += d[“thief_duration”] self.put_key_in_stealable(ts) |
我們從'可竊取的'任務鍵中抹去任務,因為我們正在制定竊取。更新任務以指向新的'盜賊'工作者,更新佔用把可竊取的任務放回盜賊,因為該工作者把任務傳送給了工作者。
self.scheduler.check_idle_saturated(thief)
self.scheduler.check_idle_saturated(victim)
最後,我們檢查並更新兩個工作者的空閒飽和狀態。空閒飽和狀態是由排程器本身保持的,此時它做一些數學運算來計算出兩個工作者的飽和狀態。
至此,我對Dask排程器的工作竊取機制的理解結束了。我在這裡的主要收穫是。
搶工被集中地整合到Dask分散式排程器中。雖然作者注意到偷工減料並不是其效能的核心組成部分,但我對Dask原始論文中的概念的實現相當好奇。目前,Dask並不支援投機性排程。我們能夠在沒有投機性排程的情況下達到Spark的許多效能基準,這一事實令人印象深刻。
Dask分散式是一個相當強大的任務分配機制,但它具有明顯的可讀性,而且決策啟發式對程式設計師是透明的。這一點我非常欣賞。
相關文章
- 一文帶你瞭解數棧百萬級分散式排程引擎DAGScheduleX分散式
- 分散式任務排程分散式
- 分散式排程任務-ElasticJob分散式AST
- LTS分散式任務排程部署分散式
- Aloha:一個分散式任務排程框架分散式框架
- 中介軟體---分散式任務排程---Celery分散式
- micro-job分散式任務排程框架更新分散式框架
- 分散式任務排程平臺XXL-JOB分散式
- 新一代分散式任務排程框架分散式框架
- Java 分散式任務排程平臺:PowerJob 快速開始+配置詳解Java分散式
- 深入工作流排程的核心
- Elastic-job實戰(分散式作業排程框架)AST分散式框架
- 分散式任務排程系統設計小結分散式
- SchedulerX 如何幫助使用者解決分散式任務排程難題?分散式
- Superior Scheduler:帶你瞭解FusionInsight MRS的超級排程器
- 你必須瞭解的分散式事務解決方案分散式
- 帶有分散式鎖的Go計劃任務排程器- DEV分散式Godev
- Spring Boot Quartz 分散式叢集任務排程實現Spring Bootquartz分散式
- 分散式後臺作業排程器JobRunr介紹 - JAXenter分散式
- 開源分散式任務排程系統就選:DolphinScheduler分散式
- Go 的搶佔式排程Go
- 深入瞭解Python的非同步IO:概念和歷史Python非同步
- 深究Python中的asyncio庫-函式的回撥與排程Python函式
- Python3 原始碼閱讀-深入瞭解Python GILPython原始碼
- 分散式任務排程內的 MySQL 分頁查詢最佳化分散式MySql
- 分散式系統架構之構建你的任務排程中心分散式架構
- Apache DolphinScheduler + OceanBase,搭建分散式大資料排程平臺的實踐Apache分散式大資料
- 基於任務排程的企業級分散式批處理方案分散式
- 深入瞭解MySQL的索引MySql索引
- 帶你快速瞭解 MongoDB 分散式叢集MongoDB分散式
- 圖解分散式架構的演進過程!圖解分散式架構
- 藉助 zope.interface 深入瞭解 Python 介面Python
- 深入瞭解JavaScript執行過程(JS系列之一)JavaScriptJS
- 分散式任務排程平臺XXL-JOB快速搭建教程分散式
- 實現一個分散式排程系統-LoadBalance和Ha策略分散式
- SpringBoot自定義starter開發分散式任務排程實踐Spring Boot分散式
- linux程式排程Linux
- 深入瞭解原型原型