面试题答案
一键面试多线程方案
在Python中,threading
模块用于多线程编程。然而,由于全局解释器锁(GIL)的存在,多线程在CPU密集型任务(如NumPy的数值计算)中并不能充分利用多核CPU的优势。但在某些情况下,如计算与I/O操作混合的场景,多线程仍可能有帮助。
- 任务分配:将大数组分割成多个小块,每个线程负责处理一块数据。
- 资源竞争与数据共享:由于NumPy数组是线程安全的,一般不需要额外的锁机制来保护数据访问。但如果多个线程需要修改同一个数组的不同部分,需要确保数据一致性。
import threading
import numpy as np
def compute_chunk(chunk):
# 这里进行复杂的数值计算,例如矩阵分解
result = np.linalg.svd(chunk)
return result
def multi_thread_compute(arr):
num_threads = 4
chunk_size = len(arr) // num_threads
threads = []
results = []
for i in range(num_threads):
start = i * chunk_size
end = start + chunk_size if i < num_threads - 1 else len(arr)
chunk = arr[start:end]
t = threading.Thread(target=lambda: results.append(compute_chunk(chunk)))
threads.append(t)
t.start()
for t in threads:
t.join()
# 这里假设可以将各个chunk的结果合并
final_result = np.concatenate(results)
return final_result
# 示例超大数组
large_array = np.random.rand(10000, 100)
result = multi_thread_compute(large_array)
print(result)
多进程方案
multiprocessing
模块可以充分利用多核CPU的优势,适合CPU密集型的NumPy计算任务。
- 任务分配:同样将大数组分割成多个小块,每个进程负责处理一块数据。
- 资源竞争与数据共享:进程间数据默认是隔离的。如果需要共享数据,可以使用
multiprocessing.Array
或multiprocessing.Value
。但对于NumPy数组,通常采用将计算结果返回,而不是在进程间共享大数组的方式。
import multiprocessing
import numpy as np
def compute_chunk(chunk):
# 这里进行复杂的数值计算,例如矩阵分解
result = np.linalg.svd(chunk)
return result
def multi_process_compute(arr):
num_processes = multiprocessing.cpu_count()
chunk_size = len(arr) // num_processes
pool = multiprocessing.Pool(processes=num_processes)
results = []
for i in range(num_processes):
start = i * chunk_size
end = start + chunk_size if i < num_processes - 1 else len(arr)
chunk = arr[start:end]
result = pool.apply_async(compute_chunk, args=(chunk,))
results.append(result)
pool.close()
pool.join()
final_results = [r.get() for r in results]
# 这里假设可以将各个chunk的结果合并
final_result = np.concatenate(final_results)
return final_result
# 示例超大数组
large_array = np.random.rand(10000, 100)
result = multi_process_compute(large_array)
print(result)
综上所述,对于纯CPU密集型的NumPy计算任务,多进程方案能更好地利用多核CPU资源提升计算速度;而多线程方案在计算与I/O混合等特定场景下可能有一定作用。