Python中如何并行实现将一个列表复制到另一个列表
有这么一个需求:需要从一个列表中( inx )查找数据的下标(inx_),然后根据下标从一个列表( pserver )复制到另外一个列表(parameters),由于 ndown 的值非常的大,循环过程很慢
for elmn in range(ndown):
inx_ = inx[elmn - ndown]
parameters[inx_] = pserver[inx_]
我考虑了多线程,但是实验效果对于 cpu 密集型的计算不是很大。 多进程也试了一下,提升也不是很大。 请问,有什么好的方法提升这个速度
Python中如何并行实现将一个列表复制到另一个列表
复制??
为什么不用切片
在Python里,并行复制列表其实是个伪需求,因为列表复制本身是CPU密集型操作,而Python的全局解释器锁(GIL)会限制多线程在CPU任务上的并行能力。用多线程来做这个,速度反而可能更慢。
不过,如果你非要“并行”处理,或者想了解模式,可以用concurrent.futures的ThreadPoolExecutor来模拟。思路是把大列表切片,让多个线程各自复制一部分,最后合并。但记住,这主要是为了演示并行模式,对纯列表复制没实际加速效果。
import concurrent.futures
import threading
def copy_chunk(source_list, start_idx, end_idx, result_list):
"""复制源列表的指定切片到结果列表的对应位置。"""
# 直接使用切片赋值进行复制
result_list[start_idx:end_idx] = source_list[start_idx:end_idx]
def parallel_list_copy(source_list, num_workers=4):
"""使用线程池并行复制列表。"""
n = len(source_list)
# 预先创建目标列表占位
result_list = [None] * n
chunk_size = (n + num_workers - 1) // num_workers # 向上取整计算每个线程处理的大小
with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as executor:
futures = []
for i in range(num_workers):
start = i * chunk_size
end = min(start + chunk_size, n) # 防止最后一个切片越界
if start >= n: # 如果起始索引已超出列表范围,则结束循环
break
# 提交任务,每个线程复制一个切片
future = executor.submit(copy_chunk, source_list, start, end, result_list)
futures.append(future)
# 等待所有任务完成(虽然这里result_list已被原地修改,但等待是良好的实践)
concurrent.futures.wait(futures)
return result_list
if __name__ == "__main__":
# 示例:创建一个包含0到999999的列表
original_list = list(range(1000000))
print("开始并行复制...")
copied_list = parallel_list_copy(original_list, num_workers=4)
print(f"原列表长度: {len(original_list)}")
print(f"复制后列表长度: {len(copied_list)}")
print(f"前10个元素是否一致: {original_list[:10] == copied_list[:10]}")
print(f"后10个元素是否一致: {original_list[-10:] == copied_list[-10:]}")
核心解释:
copy_chunk函数是每个线程执行的任务,它通过切片赋值result_list[start_idx:end_idx] = source_list[start_idx:end_idx]将源列表的一部分复制到目标列表的对应位置。这里result_list作为可变对象被所有线程共享和修改。parallel_list_copy函数是主逻辑。它先创建一个长度相同的空列表result_list,然后计算每个线程需要处理的切片大小(chunk_size)。- 使用
ThreadPoolExecutor创建线程池,为每个切片提交一个copy_chunk任务。任务会直接修改result_list的相应部分。 - 最后等待所有任务完成并返回
result_list。
重点:
- GIL限制:由于GIL,即使在多线程中,任意时刻也只有一个线程能执行Python字节码。对于
copy_chunk中的切片赋值这种操作,线程会频繁争抢GIL,导致大量上下文切换开销,所以这种并行复制对于纯CPU操作的列表复制没有性能提升,通常比简单的list.copy()或切片复制[:]更慢。 - 共享状态:这个例子中所有线程共享并修改同一个
result_list。我们通过精心划分索引范围(start,end)来确保每个线程写入不同的切片区域,避免了数据竞争。这是一种“ embarrassingly parallel ”问题的典型处理方式。 - 适用场景:这种模式更适用于每个元素处理成本较高的情况(比如每个元素需要复杂的计算或IO操作)。对于简单的复制,开销远大于收益。
一句话总结:对于纯复制,用new_list = old_list.copy()或new_list = old_list[:]最快最省事,别折腾并行。
这是把 python 当 C 用了
一楼说的对
条件允许的话用 numpy.array 会更快
1.实测(洋人实测,不是我),在列表比较大时,列表表达式比 for 循环快
建议把语句写到 fun,用[fun(x) for x in list]
2.不知道你这是举例还是正式的语句,第一句可以省略吧?改改 start/end,inx_就出来了,不必算
3.用 numpy/pandas 按条件提取很快的
不是整块复制,需要检索下标,对应复制
<br>import numpy as np<br>a = np.array([1,2,3,4,5])<br>b = np.array([6,7,8,9,10])<br>b[[0,2,4]] = a[[0,2,4]]<br><br>In [11]: b<br>Out[11]: array([1, 7, 3, 9, 5])<br>
楼主一定是不太了解 Python 的切片有多方便。
>>> a = [0,0,0,0,0,0]
>>> b = [1,2,3,4,5,6,7,8,9]
>>> a[2:5] = b[4:7]
>>> a
[0, 0, 5, 6, 7, 0]
>>>
我觉得楼主会用到多线程就不应该不会切片,估计是别的地方
不知道楼主的多进程时怎么用的?能不能用 GIST 贴一下代码
嗯,从楼短短的几行 Python 代码来看,估计楼主会用 java 的多线程 /doge/
可以试下循环展开
这是想要 MPI OpenMP 那种自动向量化吗,numpy numba cython 什么的搞吧
你多进程怎么搞的…
哈哈 洋人实测

