@spiritnotes
2016-03-05T08:15:01.000000Z
字数 2296
阅读 1978
编程题
在编程之美中有一道题目是将CPU的使用曲线按照要求显示,因此分析该题目的要点即是通过自己的程序控制CPU的使用率,按照要求合理的控制运算与Sleep的时间比。
在这里默认特定条件下(当前CPU上只有本程序运行,其他程序运行的影响很小,可忽略不计),用Python程序实现了该程序,在电脑上执行,基本合乎要求,代码如下:
#-*- coding: utf8 -*-"""控制CPU使用曲线"""import timeitimport timedef run_cpu():"""消耗CPU运算时执行的程序"""x = [_ for _ in range(RUN_RANGE_NUMBER)]def idle_cpu():"""保持CPU处于IDLE的Sleep程序"""time.sleep(SLEEP_TIME)TEST_TIME_NUMBERS = 100RUN_RANGE_NUMBER = 100000SLEEP_TIME = timeit.timeit("run_cpu()", setup="from __main__ import run_cpu", number=TEST_TIME_NUMBERS)/TEST_TIME_NUMBERSprint("测试运行100次,每次执行时间为:{}S".format(SLEEP_TIME))def run_for_1s(percent):"""1s中按照percent比例分别执行程序或者休眠"""all_times = 0.33 / SLEEP_TIMEcpu_times = all_times * percent / 100for _ in range(3):for i in range(int(all_times)):if i < cpu_times:run_cpu()else:idle_cpu()def run_sin():"""使用sin函数"""import mathi = 0while True:i = i + 1use_age = 50 + math.sin(i/5)*50run_for_1s(use_age)if __name__ == '__main__':run_sin()
针对之前的版本,如果CPU为多核,导致其使用率最多只能用到某单核的100%,,而且可能会存在程序在核间转移等情况,所以针对多核需要一个单独的版本。有如下几点:
1)由于Python中GIL的存在,因此其多线程版本可能无效,而多进程则容易将不同进程分配到不同核上,容易一致;
2)每个核上直接启动一个单核版本程序是不行的,如果启动时间有误差或者中间执行误差,会导致不同步,因此需要在中间过程中一直同步;
如下是完成的代码,主进程仍然采用单核版本同步,其在计算使用率时将该值通过queue传递给其他进程进行同步。
"""控制CPU使用曲线(多核版本)"""import timeitimport timeimport osimport multiprocessingimport mathdef run_cpu():"""消耗CPU运算时执行的程序"""x = [_ for _ in range(RUN_RANGE_NUMBER)]def idle_cpu():"""保持CPU处于IDLE的Sleep程序"""time.sleep(SLEEP_TIME)TEST_TIME_NUMBERS = 100RUN_RANGE_NUMBER = 100000SLEEP_TIME = timeit.timeit("run_cpu()", setup="from "+__name__+" import run_cpu", number=TEST_TIME_NUMBERS)/TEST_TIME_NUMBERSprint("测试运行100次,每次执行时间为:{}S".format(SLEEP_TIME))def run_for_1s(percent):"""1s中按照percent比例分别执行程序或者休眠"""all_times = 0.33 / SLEEP_TIMEcpu_times = all_times * percent / 100for _ in range(3):for i in range(int(all_times)):if i < cpu_times:run_cpu()else:idle_cpu()def run_sin(queues):"""使用sin函数"""i = 0while True:i = i + 1use_age = 50 + math.sin(i/5)*50for q in queues:q.put(use_age)run_for_1s(use_age)def run_second_process(queue, sleep_time):"""其他核的执行函数"""all_times = 1 / sleep_timewhile True:percent = queue.get()cpu_times = all_times * percent / 100for i in range(int(cpu_times)):run_cpu()def main():core_num = os.cpu_count()queues = []if core_num:for i in range(core_num-1):q = multiprocessing.Queue()queues.append(q)p = multiprocessing.Process(target=run_second_process, args=(q, SLEEP_TIME))p.start()run_sin(queues)if __name__ == '__main__':main()

