yuv*_*val 4 python multithreading multiprocessing
假设我有以下 IP 范围“10.0.0.x”。我需要在这个 ips 范围内循环 - “10.0.0.1-255”,ping 每个,并检查响应。
这是我的代码:
for ip in range(1, 256):
fullIP = '10.0.0' + ip
if(Ping(fullIP) == True):
print(fullIP + ' responded')
else:
print(fullIP + ' did not respond')
Run Code Online (Sandbox Code Playgroud)
这段代码有效,但不幸的是它很慢。
我想通过多线程提高效率,所以我做了以下事情:
def PingRange(start, end):
for ip in range(start, end):
fullIP = '10.0.0' + ip
if(Ping(fullIP) == True):
print(fullIP + ' responded')
else:
print(fullIP + ' did not respond')
try:
thread.start_new_thread( PingRange, (1, 123))
thread.start_new_thread( PingRange, (123, 256))
except:
print "Error: unable to start thread"
Run Code Online (Sandbox Code Playgroud)
这段代码也有效,但它可以更好地工作,更通用。
如果这段代码写得正确,那么我不会只是不断地创建两个线程;我会创建操作系统允许的尽可能多的线程。
有些计算机允许 8 个线程,有些计算机只允许 4 个,有些甚至不允许线程。
我怎样才能让这个程序在 Python 中使用最大数量的线程?
这个问题非常适合使用线程池。线程池以恒定数量的线程运行,获取工作项(函数或方法),并在其线程池中执行这些工作项。它具有内置队列,因此如果您将 100 个工作项分配给五个线程池,它将执行所有 100 个项目,但不会同时运行超过五个。
Python 中有两个内置线程池选项(取决于您使用的版本) -multiprocessing.dummy.Pool和concurrent.futures.ThreadPoolExecutor. ThreadPoolExecutor仅内置在 Python 3.x 中,但可从 PyPI 获得向后移植。multiprocessing.dummy.Pool在 2.6+ 中可用。使用 a multiprocessing.dummy.Pool,您的代码变得如此简单:
import multiprocessing.dummy
def ping_range(start, end):
num_threads = # Number of threads to run in the pool.
p = multiprocessing.dummy.Pool(num_threads)
p.map(ping, [10.0.0.x for x in range(start,end)])
if __name__ == "__main__":
PingRange(0, 255)
Run Code Online (Sandbox Code Playgroud)
下一个问题是用于num_threads. 我认为您对具有最大允许线程数的系统有一些误解。您可以Thread在任何系统上创建任意数量的对象,实际上没有什么可以阻止您,但是在某个时刻,您将创建如此多的线程,系统将无法处理它,性能将开始变得更糟,而不是更好。
CPU 密集型应用程序的经验法则(意味着它主要需要 CPU 来完成工作)是运行与 CPU 一样多的线程。然而,这个 ping 操作是 I/O 绑定的,这意味着大部分工作是将 ping 请求发送到外部系统,然后等待响应,这不需要 CPU 做任何事情。在这些情况下,通常可以使用超过 CPU 数量的数量。我们可以保守并使用2 * number_of_cpus,但您可以尝试使用更大的数字。
import multiprocessing
num_threads = 2 * multiprocessing.cpu_count()
Run Code Online (Sandbox Code Playgroud)
把它们放在一起:
import multiprocessing.dummy
import multiprocessing
def ping(ip):
success = # Run the ping command here
if success:
print("{} responded".format(ip))
else:
print("{} did not respond".format(ip))
return success
def ping_range(start, end):
num_threads = 2 * multiprocessing.cpu_count()
p = multiprocessing.dummy.Pool(num_threads)
p.map(ping, [10.0.0.x for x in range(start,end)])
if __name__ == "__main__":
ping_range(0, 255)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10134 次 |
| 最近记录: |