[关闭]
@spiritnotes 2016-03-05T08:15:01.000000Z 字数 2296 阅读 1742

编程之美中的CPU使用曲线编程题

编程题


题目

在编程之美中有一道题目是将CPU的使用曲线按照要求显示,因此分析该题目的要点即是通过自己的程序控制CPU的使用率,按照要求合理的控制运算与Sleep的时间比。

单核版本

在这里默认特定条件下(当前CPU上只有本程序运行,其他程序运行的影响很小,可忽略不计),用Python程序实现了该程序,在电脑上执行,基本合乎要求,代码如下:

  1. #-*- coding: utf8 -*-
  2. """
  3. 控制CPU使用曲线
  4. """
  5. import timeit
  6. import time
  7. def run_cpu():
  8. """
  9. 消耗CPU运算时执行的程序
  10. """
  11. x = [_ for _ in range(RUN_RANGE_NUMBER)]
  12. def idle_cpu():
  13. """
  14. 保持CPU处于IDLE的Sleep程序
  15. """
  16. time.sleep(SLEEP_TIME)
  17. TEST_TIME_NUMBERS = 100
  18. RUN_RANGE_NUMBER = 100000
  19. SLEEP_TIME = timeit.timeit("run_cpu()", setup="from __main__ import run_cpu", number=TEST_TIME_NUMBERS)/TEST_TIME_NUMBERS
  20. print("测试运行100次,每次执行时间为:{}S".format(SLEEP_TIME))
  21. def run_for_1s(percent):
  22. """
  23. 1s中按照percent比例分别执行程序或者休眠
  24. """
  25. all_times = 0.33 / SLEEP_TIME
  26. cpu_times = all_times * percent / 100
  27. for _ in range(3):
  28. for i in range(int(all_times)):
  29. if i < cpu_times:
  30. run_cpu()
  31. else:
  32. idle_cpu()
  33. def run_sin():
  34. """
  35. 使用sin函数
  36. """
  37. import math
  38. i = 0
  39. while True:
  40. i = i + 1
  41. use_age = 50 + math.sin(i/5)*50
  42. run_for_1s(use_age)
  43. if __name__ == '__main__':
  44. run_sin()

多核版本

针对之前的版本,如果CPU为多核,导致其使用率最多只能用到某单核的100%,,而且可能会存在程序在核间转移等情况,所以针对多核需要一个单独的版本。有如下几点:
1)由于Python中GIL的存在,因此其多线程版本可能无效,而多进程则容易将不同进程分配到不同核上,容易一致;
2)每个核上直接启动一个单核版本程序是不行的,如果启动时间有误差或者中间执行误差,会导致不同步,因此需要在中间过程中一直同步;
如下是完成的代码,主进程仍然采用单核版本同步,其在计算使用率时将该值通过queue传递给其他进程进行同步。

  1. """
  2. 控制CPU使用曲线(多核版本)
  3. """
  4. import timeit
  5. import time
  6. import os
  7. import multiprocessing
  8. import math
  9. def run_cpu():
  10. """
  11. 消耗CPU运算时执行的程序
  12. """
  13. x = [_ for _ in range(RUN_RANGE_NUMBER)]
  14. def idle_cpu():
  15. """
  16. 保持CPU处于IDLE的Sleep程序
  17. """
  18. time.sleep(SLEEP_TIME)
  19. TEST_TIME_NUMBERS = 100
  20. RUN_RANGE_NUMBER = 100000
  21. SLEEP_TIME = timeit.timeit("run_cpu()", setup="from "+__name__+" import run_cpu", number=TEST_TIME_NUMBERS)/TEST_TIME_NUMBERS
  22. print("测试运行100次,每次执行时间为:{}S".format(SLEEP_TIME))
  23. def run_for_1s(percent):
  24. """
  25. 1s中按照percent比例分别执行程序或者休眠
  26. """
  27. all_times = 0.33 / SLEEP_TIME
  28. cpu_times = all_times * percent / 100
  29. for _ in range(3):
  30. for i in range(int(all_times)):
  31. if i < cpu_times:
  32. run_cpu()
  33. else:
  34. idle_cpu()
  35. def run_sin(queues):
  36. """
  37. 使用sin函数
  38. """
  39. i = 0
  40. while True:
  41. i = i + 1
  42. use_age = 50 + math.sin(i/5)*50
  43. for q in queues:
  44. q.put(use_age)
  45. run_for_1s(use_age)
  46. def run_second_process(queue, sleep_time):
  47. """
  48. 其他核的执行函数
  49. """
  50. all_times = 1 / sleep_time
  51. while True:
  52. percent = queue.get()
  53. cpu_times = all_times * percent / 100
  54. for i in range(int(cpu_times)):
  55. run_cpu()
  56. def main():
  57. core_num = os.cpu_count()
  58. queues = []
  59. if core_num:
  60. for i in range(core_num-1):
  61. q = multiprocessing.Queue()
  62. queues.append(q)
  63. p = multiprocessing.Process(target=run_second_process, args=(q, SLEEP_TIME))
  64. p.start()
  65. run_sin(queues)
  66. if __name__ == '__main__':
  67. main()

20160122120602777.png-5.3kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注