python頻繁寫(xiě)入文件時(shí)提速的方法
問(wèn)題背景:有一批需要處理的文件,對(duì)于每一個(gè)文件,都需要調(diào)用同一個(gè)函數(shù)進(jìn)行處理,相當(dāng)耗時(shí)。
有沒(méi)有加速的辦法呢?當(dāng)然有啦,比如說(shuō)你將這些文件分成若干批,每一個(gè)批次都調(diào)用自己寫(xiě)的python腳本進(jìn)行處理,這樣同時(shí)運(yùn)行若干個(gè)python程序也可以進(jìn)行加速。
有沒(méi)有更簡(jiǎn)單的方法呢?比如說(shuō),我一個(gè)運(yùn)行的一個(gè)程序里面,同時(shí)分為多個(gè)線程,然后進(jìn)行處理?
大概思路:將這些個(gè)文件路徑的list,分成若干個(gè),至于分成多少,要看自己cpu核心有多少,比如你的cpu有32核的,理論上就可以加速32倍。
代碼如下:
# -*-coding:utf-8-*-
import numpy as np
from glob import glob
import math
import os
import torch
from tqdm import tqdm
import multiprocessing
label_path = '/home/ying/data/shiyongjie/distortion_datasets/new_distortion_dataset/train/label.txt'
file_path = '/home/ying/data/shiyongjie/distortion_datasets/new_distortion_dataset/train/distortion_image'
save_path = '/home/ying/data/shiyongjie/distortion_datasets/new_distortion_dataset/train/flow_field'
r_d_max = 128
image_index = 0
txt_file = open(label_path)
file_list = txt_file.readlines()
txt_file.close()
file_label = {}
for i in file_list:
i = i.split()
file_label[i[0]] = i[1]
r_d_max = 128
eps = 1e-32
H = 256
W = 256
def generate_flow_field(image_list):
for image_file_path in ((image_list)):
pixel_flow = np.zeros(shape=tuple([256, 256, 2])) # 按照pytorch中的grid來(lái)寫(xiě)
image_file_name = os.path.basename(image_file_path)
# print(image_file_name)
k = float(file_label[image_file_name])*(-1)*1e-7
# print(k)
r_u_max = r_d_max/(1+k*r_d_max**2) # 計(jì)算出畸變校正之后的對(duì)角線的理論長(zhǎng)度
scale = r_u_max/128 # 將這個(gè)長(zhǎng)度壓縮到256的尺寸,會(huì)有一個(gè)scale,實(shí)際上這里寫(xiě)128*sqrt(2)可能會(huì)更加直觀
for i_u in range(256):
for j_u in range(256):
x_u = float(i_u - 128)
y_u = float(128 - j_u)
theta = math.atan2(y_u, x_u)
r = math.sqrt(x_u ** 2 + y_u ** 2)
r = r * scale # 實(shí)際上得到的r,即沒(méi)有resize到256×256的圖像尺寸size,并且?guī)牍街?
r_d = (1.0 - math.sqrt(1 - 4.0 * k * r ** 2)) / (2 * k * r + eps) # 對(duì)應(yīng)在原圖(畸變圖)中的r
x_d = int(round(r_d * math.cos(theta)))
y_d = int(round(r_d * math.sin(theta)))
i_d = int(x_d + W / 2.0)
j_d = int(H / 2.0 - y_d)
if i_d < W and i_d >= 0 and j_d < H and j_d >= 0: # 只有求的的畸變點(diǎn)在原圖中的時(shí)候才進(jìn)行賦值
value1 = (i_d - 128.0)/128.0
value2 = (j_d - 128.0)/128.0
pixel_flow[j_u, i_u, 0] = value1 # mesh中存儲(chǔ)的是對(duì)應(yīng)的r的比值,在進(jìn)行畸變校正的時(shí)候,給定一張這樣的圖,進(jìn)行找像素即可
pixel_flow[j_u, i_u, 1] = value2
# 保存成array格式
saved_image_file_path = os.path.join(save_path, image_file_name.split('.')[0] + '.npy')
pixel_flow = pixel_flow.astype('f2') # 將數(shù)據(jù)的格式轉(zhuǎn)換成float16類型, 節(jié)省空間
# print(saved_image_file_path)
# print(pixel_flow)
np.save(saved_image_file_path, pixel_flow)
return
if __name__ == '__main__':
file_list = glob(file_path + '/*.JPEG')
m = 32
n = int(math.ceil(len(file_list) / float(m))) # 向上取整
result = []
pool = multiprocessing.Pool(processes=m) # 32進(jìn)程
for i in range(0, len(file_list), n):
result.append(pool.apply_async(generate_flow_field, (file_list[i: i+n],)))
pool.close()
pool.join()
在上面的代碼中,函數(shù)
generate_flow_field(image_list)
需要傳入一個(gè)list,然后對(duì)于這個(gè)list進(jìn)行操作,之后對(duì)操作的結(jié)果進(jìn)行保存
所以,只需要將你需要處理的多個(gè)文件,切分成盡量等大小的list,然后再對(duì)每一個(gè)list,開(kāi)一個(gè)線程進(jìn)行處理即可
上面的主函數(shù):
if __name__ == '__main__':
file_list = glob(file_path + '/*.JPEG') # 將文件夾下所有的JPEG文件列成一個(gè)list
m = 32 # 假設(shè)CPU有32個(gè)核心
n = int(math.ceil(len(file_list) / float(m))) # 每一個(gè)核心需要處理的list的數(shù)目
result = []
pool = multiprocessing.Pool(processes=m) # 開(kāi)32線程的線程池
for i in range(0, len(file_list), n):
result.append(pool.apply_async(generate_flow_field, (file_list[i: i+n],))) # 對(duì)每一個(gè)list都用上面我們定義的函數(shù)進(jìn)行處理
pool.close() # 處理結(jié)束之后,關(guān)閉線程池
pool.join()
主要是這樣的兩行代碼,一行是
pool = multiprocessing.Pool(processes=m) # 開(kāi)32線程的線程池
用來(lái)開(kāi)辟線程池
另外一行是
result.append(pool.apply_async(generate_flow_field, (file_list[i: i+n],))) # 對(duì)每一個(gè)list都用上面我們定義的函數(shù)進(jìn)行處理
對(duì)于線程池,用apply_async()同時(shí)跑generate_flow_field這個(gè)函數(shù),傳入的參數(shù)是:file_list[i: i+n]
實(shí)際上apply_async()這個(gè)函數(shù)的作用是所有的線程同時(shí)跑,速度是比較快的。
擴(kuò)展:
Python文件處理之文件寫(xiě)入方式與寫(xiě)緩存來(lái)提高速度和效率
Python的open的寫(xiě)入方式有:
write(str):將str寫(xiě)入文件
writelines(sequence of strings):寫(xiě)多行到文件,參數(shù)為可迭代對(duì)象
f = open('blogCblog.txt', 'w') #首先先創(chuàng)建一個(gè)文件對(duì)象,打開(kāi)方式為w
f.writelines('123456') #用readlines()方法寫(xiě)入文件
運(yùn)行上面結(jié)果之后,可以看到blogCblog.txt文件有123456內(nèi)容,這里需要注意的是,mode為‘w'模式(寫(xiě)模式),再來(lái)看下面代碼:
f = open('blogCblog.txt', 'w') #首先先創(chuàng)建一個(gè)文件對(duì)象,打開(kāi)方式為w
f.writelines(123456) #用readlines()方法寫(xiě)入文件
運(yùn)行上面代碼之后會(huì)報(bào)一個(gè)TypeError,這是因?yàn)閣ritelines傳入的參數(shù)并不是一個(gè)可迭代的對(duì)象。
以上就是關(guān)于python頻繁寫(xiě)入文件怎么提速的相關(guān)知識(shí)點(diǎn)以及擴(kuò)展內(nèi)容,感謝大家的閱讀。
相關(guān)文章
python如何獲取文件當(dāng)前位置和定位某個(gè)位置
這篇文章主要介紹了python如何獲取文件當(dāng)前位置和定位某個(gè)位置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Python word文本自動(dòng)化操作實(shí)現(xiàn)方法解析
這篇文章主要介紹了Python word文本自動(dòng)化操作實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
jupyter notebook 寫(xiě)代碼自動(dòng)補(bǔ)全的實(shí)現(xiàn)
這篇文章主要介紹了jupyter notebook 寫(xiě)代碼自動(dòng)補(bǔ)全的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Python如何生成指定區(qū)間中的隨機(jī)數(shù)
這篇文章主要介紹了Python如何生成指定區(qū)間中的隨機(jī)數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

