1. 程式人生 > >OptaPlanner 7.32.0.Final版本彩蛋 - SolverManager之批量求解

OptaPlanner 7.32.0.Final版本彩蛋 - SolverManager之批量求解

上一篇介紹了OptaPlanner 7.32.0.Final版本中的SolverManager介面可以實現非同步求解功能。本篇將繼續介紹SolverManager的另一大特性 - 批量求解。

適用場景

在日常的規劃系統中,求解一個問題,絕大多數情況下,容許執行的時間較有限,特別是在實時性較高的場景中,可讓引擎運算時間不多。因此,這種情況下,會在啟動了規劃運算後,稍等片刻,即需要從求解程式中獲取結果。但有些情況下,當我們遇到問題規模較大時,引擎無法在較短時間內找到相對最優解;甚至某些情況下,沒有足夠長的執行時間,可行解都可能無法找到。至於原因,可以參考我前面關於OptaPlanner入門文章中關於NPC, NP-Hard問題規模的說明。

因此,在一些規模大、時間要求不高的場景下,我們可以讓引擎在空餘時間自動運算。例如通過定時作業的方式,在非工作時間(例如晚間、節假日等)啟動引擎對大多個規模的問題進行規劃運算;第二天上班的時候,就可獲得運算結果。在釋出SolverManager之前,我們也完全可以針對不同的場景,設計相應的定時作業程式,讓引擎運算自動執行。當然,這種方法與非同步規劃的問題一樣,需要一定的系統設計經驗才能把架構設計完美。而7.32.0.Final版本提供的SolverManager介面,則提供一種更簡便的方法來實現些需求。

SolverManager批量規劃特性

詳細一下SolverManager介面,你應該會發現,與Solver物件的solve方法不同,使用SolverManager的sovle方法對一個問題進行求解時,除了把問題物件作為引數傳入solve方法外,還需要傳入一個problemID作為引數。其實對於這個引數很好理解,因為SolverManager可以同時對多個問題進行解,必須存在一種方法來識別不同的問題,規劃完成後,呼叫方也需要通過指定的識別號,來獲取相應的方案。SolverManager同時對多個問題進行求解時,對問題個數有何要求?它的求解行為是怎麼樣的呢?

SolverManager批量求解的行為

可同時求解多少個問題?

其實SolverManager不僅可以實現批量求解問題,而且可以實現同時對多 問題並行求解。通過設定SolverManager的parallelSolverCount屬性,可以設定引擎在批量運算時,可以並行求解的問題數。即當SolverManger啟動求解運算時,會將parallelSolverCount設定的數量的問題載入運算空間並行求解。通常parallelSolverCount值可以根據CPU、記憶體等計算機資源的情況,及問題的複雜度而推算。若無法判斷此數量,也可以將parallelSolverCount設定為AUTO,引擎會根據具體情況,自動確定並行運算問題的數量,通常情況下,並行數是CPU核心數量的一半。

值得注意的是,此處的多個問題並行運算,與之前的求解過程多執行緒運算(Multithreaded incremental solving)是兩個概念。多執行緒並行運算,指的是引擎在求解一個問題時,會將不同的可能解的子集分成多個執行緒同時計算(主要是計算約束分數和執行啟發式演算法)。而SolverManager的批量求解過程中,parallelSolverCount屬性設定的,是引擎在面對多個問題時,同時求解的問題個數。大家可以設想,如果把Multithreaded incremental solving也啟動起來,令引擎在對一個問題求解時可使用多個CPU核心,同時對多個問題並行求解。這種情況涉及的問題就沒那麼簡單。因此,除非你對問題的複雜程度,CPU的核心和運算能力非常清晰,否則上述兩個功能,還是設定為自動更好,引擎會根據計算資源運算時的工況,動態地自動確定並行求解的問題個數,及每個問題求解過程中應啟動的執行緒個數。經歷過單CPU多執行緒程式設計的朋友應該知道,多執行緒可以提高資源利用率,但有時候執行緒數量控制得不好,效能上卻是起反效果的,最簡單的是CPU的執行緒切換會消耗一定資源的。

批量求解的作用

在一些不太需要實時規劃,規劃求解不需要太頻繁,運算需時較長的情況,批量求解就可以發揮較好作用。例如需要做一些季度或年度的大型供應鏈計劃,因規劃實休數量較大,問題空間可能非常巨大,需要花費相當長的時間才能得行相對最優解,甚至只能是可行解。可通過批量求解的方式,讓引擎在空餘時間(例如晚上、非工作日)進行運算,從而提高伺服器資源的利用率。

基本用法

以下例子是OptaPlanner使用者指南的例子,大家先作參考,目前還沒有時間去研究SolverManager在示例程式中的程式碼,暫時也不知道官方示例中是否已經有SolverManager相關程式碼;若沒有,稍後的時候我自己試用一下這些功能,再寫一篇東西出來分享給大家。

public class TimeTableService {

    private SolverManager<TimeTable, Long> solverManager;

    // Returns immediately, call it for every dataset
    public void solveBatch(Long timeTableId) {
        solverManager.solve(timeTableId,
                // Called once, when solving starts
                this.findById,
                // Called once, when solving ends
                this.save);
    }

    public TimeTable findById(Long timeTableId) {...}

    public void save(TimeTable timeTable) {...}

}

 

原創不易,如果覺得文章對你有幫助,歡迎點贊、評論。文章有疏漏之處,歡迎批評指正。

本系列文章在公眾號不定時連載,請關注公眾號(讓APS成為可能)及時接收,二維碼:

http://weixin.qq.com/r/WjtFXSvE2HanrW8_925I (二維碼自動識別)


如需瞭解更多關於OptaPlanner的應用,請發電郵致:[email protected]
或到討論組發表你的意見:https://groups.google.com/forum/#!forum/optaplanner-cn
若有需要可新增本人微信(13631823503)或QQ(12977379)實時溝通,但因本人日常工作繁忙,通過微信,QQ等工具可能無法深入溝通,較複雜的問題,建議以郵件或討論組方式提出。(討論組屬於google郵件列表,國內網路可能較難訪問,需自行解