我正在嘗試使用多處理并行運行我的腳本來創建繪圖。我在這里為我的問題創建了 2 個示例腳本,因為帶有計算部分的實際主腳本會太長。在 script0.py 中,您可以看到我啟動實際 script1.py 的多處理部分,該部分并行執行 4 次。在這個例子中,它只是創建了一些隨機散點圖。
腳本0.py:
import multiprocessing as mp
import os
def execute(process):
os.system(f"python {process}")
if __name__ == "__main__":
proc_num = 4
process= []
for _ in range(proc_num):
process.append("script1.py")
process_pool = mp.Pool(processes= proc_num)
process_pool.map(execute, process)
腳本1.py:
#just a random scatterplot, but works for my example
import time
import numpy as np
import matplotlib.pyplot as plt
import os
dir_name = "stackoverflow_question"
plot_name = time.strftime("Plot %Hh%Mm%Ss") #note the time.strftime() function
if not os.path.exists(f"{dir_name}"):
os.mkdir(f"{dir_name}")
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = (30 * np.random.rand(N))**2
plt.scatter(x,y, s=area, c=colors, alpha=0.5)
#plt.show()
plt.savefig(f"{dir_name}/{plot_name}", dpi = 300)
重要的是,我以情節的創作時間命名
plot_name = time.strftime("繪圖 %Hh%Mm%Ss")
所以這會創建一個類似“Plot 16h39m22s”的字串。到目前為止一切順利......現在是我的實際問題!我意識到,在并行啟動行程時,有時繪圖名稱是相同的,因為 time.strftime() 創建的時間戳是相同的,因此可能會發生 script1.py 的一個實體覆寫另一個已經創建的繪圖.
在我遇到這個確切問題的作業腳本中,我生成了大量資料,因此我需要根據它們的生成日期和時間來命名我的圖和 CSV。
我已經想過在 script1.py 被呼叫時給它一個變數,但我不知道如何實作這一點,因為我剛剛了解了多處理庫。但是這個變數也必須改變,否則我會遇到同樣的問題。
有人對我如何實作這一點有更好的了解嗎?非常感謝你。
uj5u.com熱心網友回復:
我提出這些方法:
- 方法1:(簡單且推薦)如果您可以更改名稱,我建議使用unixtime(例如使用time.time()或time.time_ns())而不是日期或將小數添加到秒。這樣你就幾乎不可能發生碰撞。
- 方法2:在檔案名中添加行程ID(例如:<filename_timestamp_processid>)。這樣,即使兩個行程同時寫入,您也將擁有區分檔案的行程 ID。如果要在執行結束時從名稱中洗掉 id,請讀取檔案名并進行合并,如果有沖突,請以適當的方式調整檔案名。
- 方法 3:與方法 2 類似,但不是更改名稱,而是創建一個以行程 ID 命名的檔案夾,在其中放置該行程的輸出。在執行結束時,您合并檔案夾并更正任何沖突。
- 方法四:(不推薦,難管理,影響性能)共享記憶體。您在共享記憶體中使用帶有最后一個時間戳的變數并檢查它。
uj5u.com熱心網友回復:
歡迎來到本站。幾個想法...
首先,您沒有遵循multiprocessing
模塊中關于如何使用Pool
. 你應該把它放在背景關系管理器中,with(...)...
那里有很多例子。請參閱 dox 中的紅色警告:
https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool
此外,使用os.system
呼叫有點奇怪/不安全。為什么不將繪圖例程放入同一模塊或不同模塊中的標準函式中并匯入它?這將允許您將附加資訊(如一個好的標簽)傳遞給該函式。我希望這樣的東西在哪里source
是資料檔案或外部源......
def make_plot(source, output_file_name, plot_label):
# read the data source
# make the plot
# save it to the output path...
就標簽而言,如果您在同一個“秒”內啟動這些行程,當然會有重疊,因此您可以在標簽上附加行程號,或者附加一些其他資訊,例如來自資料源,或使用相同的時間戳,但將輸出放在唯一的檔案夾中,如另一個答案中所建議的那樣。
我會想這樣的事情......
代碼:
from multiprocessing import Pool
import time
def f(data, output_folder, label):
# here data is just an integer, in yours, it would be the source of the graph data...
val = data * data
# the below is just example... you could just use your folder making/saving routine...
return f'now we can save {label} in folder {output_folder} with value: {val}'
if __name__ == '__main__':
with Pool(5) as p:
folders = ['data1', 'data2', 'data3']
labels = [time.strftime("Plot %Hh%Mm%Ss")]*3
x_s = [1, 2, 3]
output = p.starmap(f, zip(x_s, folders, labels))
for result in output:
print(result)
輸出:
now we can save Plot 08h55m17s in folder data1 with value: 1
now we can save Plot 08h55m17s in folder data2 with value: 4
now we can save Plot 08h55m17s in folder data3 with value: 9
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/506953.html