[英]Force TPL Tasks to run on a single core
我有 ETL 項目,它有一些處理組件。 單個組件是基於 BlockingCollection 的生產者-消費者。 所有組件都通過 Task.Run 並行執行,等待來自其他組件的項目到達,處理它們並將結果放入它們的輸出集合(想想管道)。 所有組件都通過 Task.Run() 執行。
是否可以強制任務在單核上運行(我不希望它們占用 100% 的多核 CPU)而不為進程設置處理器關聯(這似乎有點矯枉過正)?
請注意,我仍然希望任務以並行方式運行 - 僅在單個內核上運行。
任務在線程上執行,操作系統決定它執行哪個核心。
我認為除了設置 Processor Affinity 之外沒有其他任何方法。
請參閱此處: https : //msdn.microsoft.com/en-us/library/system.diagnostics.processthread.processoraffinity.aspx
您確定在一個內核上並行運行它們將使您受益於性能,為什么您不希望該進程在需要時可能使用 100% cpu? 操作系統仍然會優先考慮其他進程,而不是一定允許這樣做
如果您擔心您的進程對其他操作系統進程造成壓力,您也可以降低線程/進程優先級:
進程優先級: https : //msdn.microsoft.com/en-us/library/system.diagnostics.process.priorityclass.aspx線程優先級: https : //msdn.microsoft.com/en-us/library/system.threading .thread.priority(v=vs.110).aspx
是的,這是完全可能的。 你只需要實現你自己的TaskScheduler 。
實際上,TaskSchduler 的 API 文檔中的示例說明了如何准確完成您想要的操作——它們實現了LimitedConcurrencyLevelTaskScheduler
,讓您可以設置要使用的工作線程數。
API 文檔的備注部分中的鏈接也很有價值。 使用 .NET Framework 4項目進行並行編程的示例包含大量替代線程調度程序,在此處詳細描述。 它們可能會激發您思考安排這些任務的替代方法。
這里唯一的扭曲是您不能再使用Task.Run()
快捷方式——您需要通過 TaskFactory 來代替。
使用Task.Run()
,您對作業的控制非常低,並且一切都是並行的,除非您使用自定義調度程序。
我建議使用Task Parallel Library (TPL)而不是這種技術解決方案,它可以被視為處理線程作業的更高層。
在 TPL 中,您可以選擇塊類型來處理您的數據,甚至可以將它們之間的塊連接起來,這樣當一個項目剛剛完成處理時,結果就可以在下一個 TPL 塊中排隊。
您可以使用ActionBlock<T>
:您定義要為每個要處理的項目執行的代碼,並且當數據可用於 ActionBlock 時,使用.Post()
,它會自動處理......並行。 但根據您的需要,您可以指定MaxDegreeOfParallelism=1
。
因此,使用這種方法,您無法控制執行代碼的核心,但您可以確保所有項目都將按順序處理,並且一次不會使用多個核心。
var workerBlock = new ActionBlock<int>(
// Simulate work by suspending the current thread.
millisecondsTimeout => Thread.Sleep(millisecondsTimeout),
// Specify a maximum degree of parallelism.
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 1
});
// Source: https://docs.microsoft.com/fr-fr/dotnet/api/system.threading.tasks.dataflow.actionblock-1?view=netcore-3.1
你也可以閱讀這篇關於 TPL 的完整文章,非常有趣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.