我正在执行一项操作,我们称之为CalculateSomeData。 CalculateSomeData以连续的“代”运行,编号为1..x。整个运行中的代数由CalculateSomeData的输入参数确定,并且是先验已知的。一代人需要30分钟到2个小时才能完成。一些可变性是由输入参数引起的,无法控制。但是,这种可变性的一部分是由于硬件容量,来自其他进程的CPU负载,网络带宽负载等因素。每代可以控制的一个参数是CalculateSomeData使用的线程数。现在这是固定的,可能不是最优的。我想跟踪每一代所花费的时间,然后使用一些算法来调整线程的数量,以便每一代连续生成改进上一代的计算时间(最小化时间)。我应该使用什么方法?遗传算法有多适用? Intuition告诉我,范围将相当紧张 - 在双四核处理器机器上可能有1到16个线程。
任何指针,伪代码等都非常感激。
答案 0 :(得分:2)
如果计算完全受CPU限制,则线程数应等于计算机上的核心数。这样就可以最小化上下文切换次数。
如果您的计算涉及I / O,网络,同步或阻止执行的其他事项,则必须找到限制资源并测量利用率。您需要监视利用率并缓慢添加更多线程,直到利用率接近100%。你应该尽可能少的线程来使你的限制资源饱和。
答案 1 :(得分:2)
进化算法怎么样。
开始猜测。每个CPU核心1个线程看起来不错,但取决于手头的任务。
衡量一代中每项任务的平均时间。将其与上一代所花费的时间进行比较。 (假设生成0有效无限时间和0个线程)。
如果最近一代的任务平均时间比以前更好,那么继续改变与上一步相同方向的线程数(所以如果上一代的线程比前一个线程多,那么添加新一代的一个线程,但如果它少了,那么少用一个(显然有1个线程的下限)。
如果最近一代的任务平均花费的时间比上一代要长,那么改变相反方向的线程数(因此,如果增加线程数导致时间更短,则下次使用少一个线程)
只要最佳线程数不太接近1,那么您可能最终会在3个值之间振荡,这些值都非常接近最佳值。如果您需要处理大量代数,您可能希望明确检测此案例并将自己锁定为中心值。
答案 2 :(得分:1)
您应该将您的世代分成许多小任务并将它们放入队列中。每个核心生成一个线程并让每个线程抓住要执行的任务,将其运行完成,然后重复。
您需要比核心更多的任务,以确保您最终只能在生成结束时运行一个任务,而所有其他线程都空闲。如果您按照Albin的建议设置#tasks = #threads = #cores,则可能会发生这种情况(除非您可以确保所有任务花费的时间相同)。
您可能也不希望线程多于核心。上下文切换并不是非常昂贵,但是除了#cores任务同时处于活动状态之外,更大的缓存占用空间可能会对您造成伤害(除非您的任务使用非常少的内存)。