Đây phải là câu hỏi thứ ba và cuối cùng của tôi về những nỗ lực tăng hiệu suất trên một số phân tích thống kê mà tôi đang thực hiện với python. Tôi có 2 phiên bản mã của tôi (lõi đơn so với đa xử lý), tôi đã mong đợi đạt được hiệu suất bằng cách sử dụng nhiều lõi như tôi mong đợi mã của tôi giải nén/giải nén một vài chuỗi nhị phân, đáng buồn là tôi nhận thấy hiệu suất thực sự giảm bằng cách sử dụng nhiều lõi.Khả năng xử lý đa xử lý Python
Tôi tự hỏi nếu có ai có lời giải thích có thể cho những gì tôi quan sát (cuộn xuống bản cập nhật ngày 16 tháng 4 để biết thêm thông tin)?
Phần chính của chương trình là hàm numpy_array (+ decode trong đa), đoạn mã dưới đây (mã đầy đủ truy cập qua pastebin, thêm dưới đây):
def numpy_array(data, peaks):
rt_counter=0
for x in peaks:
if rt_counter %(len(peaks)/20) == 0:
update_progress()
peak_counter=0
data_buff=base64.b64decode(x)
buff_size=len(data_buff)/4
unpack_format=">%dL" % buff_size
index=0
for y in struct.unpack(unpack_format,data_buff):
buff1=struct.pack("I",y)
buff2=struct.unpack("f",buff1)[0]
if (index % 2 == 0):
data[rt_counter][1][peak_counter][0]=float(buff2)
else:
data[rt_counter][1][peak_counter][1]=float(buff2)
peak_counter+=1
index+=1
rt_counter+=1
Phiên bản đa thực hiện điều này với một tập hợp các chức năng, tôi sẽ hiển thị phím 2 dưới đây:
def tonumpyarray(mp_arr):
return np.frombuffer(mp_arr.get_obj())
def numpy_array(shared_arr,peaks):
processors=mp.cpu_count()
with contextlib.closing(mp.Pool(processes=processors,
initializer=pool_init,
initargs=(shared_arr,))) as pool:
chunk_size=int(len(peaks)/processors)
map_parameters=[]
for i in range(processors):
counter = i*chunk_size
chunk=peaks[i*chunk_size:(i+1)*chunk_size]
map_parameters.append((chunk, counter))
pool.map(decode,map_parameters)
def decode ((chunk, counter)):
data=tonumpyarray(shared_arr).view(
[('f0','<f4'), ('f1','<f4',(250000,2))])
for x in chunk:
peak_counter=0
data_buff=base64.b64decode(x)
buff_size=len(data_buff)/4
unpack_format=">%dL" % buff_size
index=0
for y in struct.unpack(unpack_format,data_buff):
buff1=struct.pack("I",y)
buff2=struct.unpack("f",buff1)[0]
#with shared_arr.get_lock():
if (index % 2 == 0):
data[counter][1][peak_counter][0]=float(buff2)
else:
data[counter][1][peak_counter][1]=float(buff2)
peak_counter+=1
index+=1
counter+=1
mã đầy đủ chương trình có thể được truy cập thông qua những liên kết này pastebin
Pastebin for single core version
Pastebin for multiprocessing version
Việc thực hiện mà tôi đang quan sát với một tập tin chứa 239 timepoints và ~ cặp đo 180k mỗi timepoint là ~ 2.5m cho lõi đơn và ~ 3.5 cho đa xử lý.
PS: Hai câu hỏi trước đó (của đầu tiên của tôi bao giờ cố gắng ở paralellization):
- 16 tháng tư -
Tôi đã lược tả chương trình của mình bằng t ông thư viện cProfile (có cProfile.run('main()')
trong __main__
, trong đó cho thấy rằng có 1 bước mà đang chậm lại tất cả mọi thứ xuống:
ncalls tottime percall cumtime percall filename:lineno(function)
23 85.859 3.733 85.859 3.733 {method 'acquire' of 'thread.lock' objects}
Điều mà tôi không hiểu ở đây là thread.lock
đối tượng được sử dụng trong threading
(để hiểu biết của tôi) nhưng không nên được sử dụng trong đa xử lý như mỗi lõi nên chạy một thread duy nhất (bên cạnh việc có cơ chế khóa riêng của nó), vậy làm thế nào nó xảy ra và tại sao một cuộc gọi duy nhất mất 3,7 giây?
bạn có thể chia sẻ liên kết tới câu hỏi trước của mình trong câu hỏi này không? và dán các hàm bạn cho là quan trọng đối với câu hỏi – 0x90
Offcourse, hãy để tôi chỉnh sửa câu hỏi. –
Nó rất tốt có thể có một cái gì đó để làm với GIL. Xem bản trình bày này: http://www.youtube.com/watch?v=Obt-vMVdM8s – alexhb