[英]What is a good number of partitions in spark as a function of number of executors and threads?
我在EMR上使用Spark。 我啟動集群,有時集群很小(在編寫/測試代碼時),例如5-10個實例。 其他時間則使用大量實例(例如30-50)執行同一代碼。
我知道我可以訪問配置以幫助設置分區數,選擇合適的分區數有助於運行時。
我想根據執行程序的數量和線程的數量來參數化分區的數量:
val instanceCount = sc.getConf.get("spark.executor.instances").toDouble
val coreCount = sc.getConf.get("spark.executor.cores").toDouble
有沒有人研究過這個問題,並且可以就分區數量的參數化提供任何建議?
我意識到沒有一個好的答案,而是某種函數形式,常量將有所幫助。 例如:
val partitionCount = instanceCount*coreCount*0.7
在我的用例中似乎工作得很好,並描述您的用例(執行者的數量/范圍),這將有所幫助。
在答案中,如果您可以指出實例的范圍,那么您的工作也會很有幫助。 如果在某處對此進行了規范的調查,則指向該點的指針將有所幫助。
沒有針對所有用例的最佳配置,但是我將為您提供我在Spark體驗中收集的所有啟發式方法。
首先,讓我們說明一下顯而易見的內容。 您需要的分區(給定階段中的任務)比內核更多,否則某些內核將無所事事。 此經驗法則是否有例外? 是:
spark.scheduler.mode=FAIR
在單個步驟內或在自定義托管的YARN集群上spark.scheduler.mode=FAIR
。 我從來沒有嘗試過提交並行的EMR步驟,也不知道是否有可能,這不是常規的YARN概念(但同樣,如果需要,您可以在同一步驟中完成)。 小分區會導致作業變慢,因為驅動程序和從屬之間存在一定量的通信,如果您有10萬個小任務,這確實會占用大量時間。 如果您的任務在1秒內完成,則分區肯定太小。
反之,大分區會損害內存,尤其是在隨機播放期間。 隨機播放對內存的要求很高,將使您進行大量垃圾收集。 如果分區太大,則會增加內存用盡的風險,或者最好將50%以上的時間花費在GC上。 序列化形式的2GB是分區大小的絕對限制,因為Spark使用Java Java IO實用程序,該實用程序由字節數組支持,該字節數組只能容納2^31 - 1
( int
大小)個元素。
通常,如果您要進行隨機播放(通常在這里談論JSON和文本數據),我建議壓縮格式大約為25MB-70MB。
如果您需要向所有執行者廣播一些對象(例如,布隆過濾器以在改組數據集之前減小其大小),則所需的容器數將由您願意在其上使用的內存量決定。每台機器都可以保存您的廣播。 實際上,每個執行器將廣播一次該對象,因此,假設同構集群,每台計算機的廣播數據量為object_size * num_executors / num_ec2_instances
。 網絡成本也隨着容器數量的增加而增加,因為該對象需要多次廣播到每個EC2實例。
但是,我遇到的情況是我的廣播對象是一個邏輯模型,該模型在分類過程中使用了一些內部可變狀態。 這意味着predict方法已同步,並且容器中的所有線程都在爭奪訪問此鎖的權限。 通過增加容器的數量(從而增加廣播的內存和網絡成本),我使這項工作快了4倍。
分區的數量由數據的大小決定,而不是由可用內核的數量決定。 如果您的數據不需要超過200個分區,那么就不要采用大於200個核心的群集,如果分區的大小已經足夠合理,那么增加分區和核心的數量可能不會有任何有意義的速度。
只要您的數據大小合適且分區平衡,則剩下的唯一試探法是:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.