主頁 > 軟體工程 > 在for回圈中使用預加載資料的執行緒安全方式

在for回圈中使用預加載資料的執行緒安全方式

2022-01-05 12:34:54 軟體工程

賞金過期5天回答這個問題有資格獲得 50聲望獎勵。 quantguy引起更多人對這個問題的關注

假設我們在 for 回圈中對幾乎相同的基本資料(可變)應用一組(就地)操作。什么是記憶體高效(和執行緒安全)的方式來做到這一點?

請注意,在每次迭代的 for 回圈中不應更改基本資料。

示例代碼:

假設我們在一個data目錄中有一些包含基本資料的 Excel 檔案此外,我們在some_more_data目錄中有一些附加資料我想data使用目錄中的檔案對從some_more_data目錄中檢索到的資料應用操作之后我想將結果列印到一個新的泡菜檔案中。

import copy
import pickle
import pandas as pd

# Excel import function to obtain dictionary of pandas DataFrames.
def read_data(info_dict):

   data_dict = dict()
   for dname, dpath in info_dict.items():
       data_dict[dname] = pd.read_excel(dpath, index_col=0)

   return data_dict

# list of data files
data_list = {'price': 'data/price.xlsx', 'eps': 'data/eps.xlsx'}
raw_data = read_data(data_list)

# list of files used for operation (they, for example, have different indices)
some_more_data= {
    'some_data_a': 'some_more_data/some_data_a.xlsx',
    'some_data_b': 'some_more_data/some_data_b.xlsx'
    }
some_more_data = read_data(some_more_data)

# Apply operation to data (explicitly use a for-loop)
for smd_k, smd_v in some_more_data.items():
   rdata = copy.deepcopy(raw_data)

   rdata['price'] = rdata['price'].reindex(smd_v.index)
   rdata['eps'] = rdata['eps'].reindex(columns=smd_v.columns)

   with open(f'data/changed_{smd_k}.pkl', 'wb') as handle:
        pickle.dump(rdata, handle, protocol=pickle.HIGHEST_PROTOCOL)

我上面示例中的 deepcopy 操作是否執行緒安全(假設我想使用多執行緒)?或者我應該在 for 回圈中重復加載 Excel 中的資料(非常慢)?或者有更好的方法嗎?

謝謝您的幫助。


用于生成示例資料幀并將資料保存在 Excel 檔案中的代碼

注意目錄datasome_more_data必須先手動創建

import pandas as pd
import numpy as np


price = pd.DataFrame([[-1.332298,  0.396217,  0.574269, -0.679972, -0.470584,  0.234379],
                      [-0.222567,  0.281202, -0.505856, -1.392477,  0.941539,  0.974867],
                      [-1.139867, -0.458111, -0.999498,  1.920840,  0.478174, -0.315904],
                      [-0.189720, -0.542432, -0.471642,  1.506206, -1.506439,  0.301714]],
                     columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                     index=pd.date_range('2000', freq='D', periods=4))

eps = pd.DataFrame([[-1.91,  1.63,  0.51, -.32, -0.84,  0.37],
                      [-0.56,  0.02, 0.56, 1.77,  0.99,  0.97],
                      [-1.67, -0.41, -0.98,  1.20,  0.74, -0.04],
                      [-0.80, -0.43, -0.12,  1.06, 1.59,  0.34]],
                     columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], 
                     index=pd.date_range('2000', freq='D', periods=4))

some_data_a = pd.DataFrame(np.random.randint(0,100,size=(4, 6)), columns=['IBM', 'MSFT', 'APPL', 'ORCL','FB','TWTR'], index=pd.date_range('2001', freq='D', periods=4))
some_data_b = pd.DataFrame(np.random.randint(0,100,size=(20, 6)), columns=['GM', 'TSLA', 'IBM', 'MSFT', 'APPL', 'ORCL'], index=pd.date_range('2000', freq='D', periods=20))

price.to_excel('data/price.xlsx')
eps.to_excel('data/eps.xlsx')
some_data_a.to_excel('some_more_data/some_data_a.xlsx')
some_data_b.to_excel('some_more_data/some_data_b.xlsx')

uj5u.com熱心網友回復:

一旦你的raw_data字典被創建,我看不到它在哪里被修改(畢竟,這使用deepcopy它的重點)。因此,雖然深度復制可變物件不是執行緒安全的,但這個特定物件在任何時候都不會發生變化。所以我不明白為什么會有問題。但是,deepcopy如果您沒有信心,您總是可以在鎖的控制下進行。

如果您使用多執行緒執行此操作,那么使用 athreading.Lock可能不會降低性能,因為深度復制操作都是 CPU 并且deepcopy無論如何您都無法實作任何并行性,因為您的執行緒已經為此鎖定了全域解釋器鎖 (GIL)函式(主要是 Python 位元組碼)。這種額外的鎖定只是防止在deepcopy操作程序中放棄你的時間片給另一個可能開始一個執行緒的執行緒deepcopy操作(但同樣,我仍然認為這不是問題)。但是,如果您使用多執行緒,那么并發 I/O 操作會帶來哪些性能提升?根據您使用的是硬碟驅動器還是固態驅動器以及該驅動器的特性,并發甚至可能會損害您的 I/O 性能。Pandas如果他們發布 GIL,您可能會從這些操作中獲得一些性能改進

多處理確實提供了 CPU 密集型功能的真正并行性,在創建行程和將資料從一個地址空間傳遞到另一個地址空間(即一個行程到另一個行程)方面有自己的開銷。這種在串行處理中沒有的額外開銷必須通過并行計算所實作的節省來補償。從您所展示的內容中不清楚,如果這確實代表了您的實際情況,那么您將從這種并行性中獲得任何好處。但是,當然,您不必擔心執行緒安全性,deepcopy因為一旦每個行程都有該行程的副本raw_data,就會運行一個執行緒,該執行緒擁有自己的記憶體副本,彼此完全隔離。

概括

  1. 通常,deepcopy對于可變物件不是執行緒安全的,但由于您的物件似乎沒有“變異”,因此應該不是問題。但是如果在多執行緒下運行,您可以deepcopy在 a 控制下操作作為原子操作執行,multithreading.Lock而不會顯著降低性能。

  2. 如果您正在使用多處理,并假設raw_data沒有在共享記憶體中實作,那么每個行程將raw_data開始處理自己的副本因此,即使另一個行程正在“變異” raw_data,只要任何一個行程正在運行單個執行緒,就無需擔心deepcopy.

  3. 根據我所看到的代碼,目前尚不清楚多執行緒或多處理是否會實作任何性能改進。

基準

這對串行、多執行緒和多處理進行了基準測驗。也許每個字典中只有 2 個鍵,這不是一個現實的例子,但它給出了一個總體思路:

import copy
import pickle
import pandas as pd
import time
from multiprocessing.pool import Pool, ThreadPool
from multiprocessing import cpu_count


# Excel import function to obtain dictionary of pandas DataFrames.
def read_data(info_dict):

   data_dict = dict()
   for dname, dpath in info_dict.items():
       data_dict[dname] = pd.read_excel(dpath, index_col=0)

   return data_dict

def serial(raw_data, some_more_data, suffix):
    # Apply operation to data (explicitly use a for-loop)
    for smd_k, smd_v in some_more_data.items():
       rdata = copy.deepcopy(raw_data)

       rdata['price'] = rdata['price'].reindex(smd_v.index)
       rdata['eps'] = rdata['eps'].reindex(columns=smd_v.columns)

       with open(f'data/changed_{smd_k}_{suffix}.pkl', 'wb') as handle:
            pickle.dump(rdata, handle, protocol=pickle.HIGHEST_PROTOCOL)

def init_pool(r_d, sfx):
    global raw_data, suffix
    raw_data = r_d
    suffix = sfx

def worker(smd_k, smd_v):
    rdata = copy.deepcopy(raw_data)

    rdata['price'] = rdata['price'].reindex(smd_v.index)
    rdata['eps'] = rdata['eps'].reindex(columns=smd_v.columns)

    with open(f'data/changed_{smd_k}_{suffix}.pkl', 'wb') as handle:
         pickle.dump(rdata, handle, protocol=pickle.HIGHEST_PROTOCOL)

def benchmark1(raw_data, some_more_data):
    start_time = time.time()
    serial(raw_data, some_more_data, '1')
    elapsed = time.time() - start_time
    print('Serial time:', elapsed)

def benchmark2(raw_data, some_more_data):
    start_time = time.time()
    items = list(some_more_data.items())
    pool_size = len(items)
    pool = ThreadPool(pool_size, initializer=init_pool, initargs=(raw_data, '2'))
    pool.starmap(worker, items)
    elapsed = time.time() - start_time
    print('Multithreading time:', elapsed)
    pool.close()
    pool.join()

def benchmark3(raw_data, some_more_data):
    start_time = time.time()
    items = list(some_more_data.items())
    pool_size = min(len(items), cpu_count())
    pool = Pool(pool_size, initializer=init_pool, initargs=(raw_data, '3'))
    pool.starmap(worker, items)
    elapsed = time.time() - start_time
    print('Multiprocessing time:', elapsed)
    pool.close()
    pool.join()

def main():
# list of data files
    data_list = {'price': 'data/price.xlsx', 'eps': 'data/eps.xlsx'}
    raw_data = read_data(data_list)

    # list of files used for operation (they, for example, have different indices)
    some_more_data= {
        'some_data_a': 'some_more_data/some_data_a.xlsx',
        'some_data_b': 'some_more_data/some_data_b.xlsx'
        }
    some_more_data = read_data(some_more_data)

    benchmark1(raw_data, some_more_data)
    benchmark2(raw_data, some_more_data)
    benchmark3(raw_data, some_more_data)

if __name__ == '__main__':
    main()

印刷:

Serial time: 0.002997159957885742
Multithreading time: 0.013999462127685547
Multiprocessing time: 0.7790002822875977

轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/403793.html

標籤:

上一篇:正則運算式匹配/中斷

下一篇:[Azure DevOps] 管理測驗計劃、測驗套件和測驗用例

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • Git本地庫既關聯GitHub又關聯Gitee

    創建代碼倉庫 使用gitee舉例(github和gitee差不多) 1.在gitee右上角點擊+,選擇新建倉庫 ? 2.選擇填寫倉庫資訊,然后進行創建 ? 3.服務端已經準備好了,本地開始作準備 (1)Git 全域設定 git config --global user.name "成鈺" git c ......

    uj5u.com 2020-09-10 05:04:14 more
  • CODING DevOps 代碼質量實戰系列第二課,相約周三

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。**《DevOps 代碼質量實戰(PHP 版)》**為 CODING DevOps 代碼質量實戰系列的第二課,同時也是本系列的 PHP ......

    uj5u.com 2020-09-10 05:07:43 more
  • 推薦Scrum書籍

    推薦Scrum書籍 直接上干貨,推薦書籍清單如下(推薦有順序的哦) Scrum指南 Scrum精髓 Scrum敏捷軟體開發 Scrum捷徑 硝煙中的Scrum和XP : 我們如何實施Scrum 敏捷軟體開發:Scrum實戰指南 Scrum要素 大規模Scrum:大規模敏捷組織的設計 用戶故事地圖 用 ......

    uj5u.com 2020-09-10 05:07:45 more
  • CODING DevOps 代碼質量實戰系列最后一課,周四發車

    隨著 ToB(企業服務)的興起和 ToC(消費互聯網)產品進入成熟期,線上故障帶來的損失越來越大,代碼質量越來越重要,而「質量內建」正是 DevOps 核心理念之一。 **《DevOps 代碼質量實戰(Java 版)》**為 CODING DevOps 代碼質量實戰系列的最后一課,同時也是本系列的 ......

    uj5u.com 2020-09-10 05:07:52 more
  • 敏捷軟體工程實踐書籍

    Scrum轉型想要做好,第一步先了解并真正落實Scrum,那么我推薦的Scrum書籍是要看懂并實踐的。第二步是團隊的工程實踐要做扎實。 下面推薦工程實踐書單: 重構:改善既有代碼的設計 決議極限編程 : 擁抱變化 代碼整潔代碼 程式員的職業素養 修改代碼的藝術 撰寫可讀代碼的藝術 測驗驅動開發 : ......

    uj5u.com 2020-09-10 05:07:55 more
  • Jenkins+svn+nginx實作windows環境自動部署vue前端專案

    前面文章介紹了Jenkins+svn+tomcat實作自動化部署,現在終于有空抽時間出來寫下Jenkins+svn+nginx實作自動部署vue前端專案。 jenkins的安裝和配置已經在前面文章進行介紹,下面介紹實作vue前端專案需要進行的哪些額外的步驟。 注意:在安裝jenkins和nginx的 ......

    uj5u.com 2020-09-10 05:08:49 more
  • CODING DevOps 微服務專案實戰系列第一課,明天等你

    CODING DevOps 微服務專案實戰系列第一課**《DevOps 微服務專案實戰:DevOps 初體驗》**將由 CODING DevOps 開發工程師 王寬老師 向大家介紹 DevOps 的基本理念,并探討為什么現代開發活動需要 DevOps,同時將以 eShopOnContainers 項 ......

    uj5u.com 2020-09-10 05:09:14 more
  • CODING DevOps 微服務專案實戰系列第二課來啦!

    近年來,工程專案的結構越來越復雜,需要接入合適的持續集成流水線形式,才能滿足更多變的需求,那么如何優雅地使用 CI 能力提升生產效率呢?CODING DevOps 微服務專案實戰系列第二課 《DevOps 微服務專案實戰:CI 進階用法》 將由 CODING DevOps 全堆疊工程師 何晨哲老師 向 ......

    uj5u.com 2020-09-10 05:09:33 more
  • CODING DevOps 微服務專案實戰系列最后一課,周四開講!

    隨著軟體工程越來越復雜化,如何在 Kubernetes 集群進行灰度發布成為了生產部署的”必修課“,而如何實作安全可控、自動化的灰度發布也成為了持續部署重點關注的問題。CODING DevOps 微服務專案實戰系列最后一課:**《DevOps 微服務專案實戰:基于 Nginx-ingress 的自動 ......

    uj5u.com 2020-09-10 05:10:00 more
  • CODING 儀表盤功能正式推出,實作作業資料可視化!

    CODING 儀表盤功能現已正式推出!該功能旨在用一張張統計卡片的形式,統計并展示使用 CODING 中所產生的資料。這意味著無需額外的設定,就可以收集歸納寶貴的作業資料并予之量化分析。這些海量的資料皆會以圖表或串列的方式躍然紙上,方便團隊成員隨時查看各專案的進度、狀態和指標,云端協作迎來真正意義上 ......

    uj5u.com 2020-09-10 05:11:01 more
最新发布
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:41:12 more
  • windows系統git使用ssh方式和gitee/github進行同步

    使用git來clone專案有兩種方式:HTTPS和SSH:
    HTTPS:不管是誰,拿到url隨便clone,但是在push的時候需要驗證用戶名和密碼;
    SSH:clone的專案你必須是擁有者或者管理員,而且需要在clone前添加SSH Key。SSH 在push的時候,是不需要輸入用戶名的,如果配置... ......

    uj5u.com 2023-04-19 08:35:34 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:05:44 more
  • 2023年農牧行業6大CRM系統、5大場景盤點

    在物聯網、大資料、云計算、人工智能、自動化技術等現代資訊技術蓬勃發展與逐步成熟的背景下,數字化正成為農牧行業供給側結構性變革與高質量發展的核心驅動因素。因此,改造和提升傳統農牧業、開拓創新現代智慧農牧業,加快推進農牧業的現代化、資訊化、數字化建設已成為農牧業發展的重要方向。 當下,企業數字化轉型已經 ......

    uj5u.com 2023-04-18 08:00:18 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:20:31 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:55 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:18:51 more
  • 談一談我對協同開發的一些認識

    如今各互聯網公司普通都使用敏捷開發,采用小步快跑的形式來進行專案開發。如果是小專案或者小需求,那一個開發可能就搞定了。但對于電商等復雜的系統,其功能多,結構復雜,一個人肯定是搞不定的,所以都是很多人來共同開發維護。以我曾經待過的商城團隊為例,光是后端開發就有七十多人。 為了更好地開發這類大型系統,往 ......

    uj5u.com 2023-04-17 08:18:00 more
  • 專案管理PRINCE2核心知識點整理

    PRINCE2,即 PRoject IN Controlled Environment(受控環境中的專案)是一種結構化的專案管理方法論,由英國政府內閣商務部(OGC)推出,是英國專案管理標準。
    PRINCE2 作為一種開放的方法論,是一套結構化的專案管理流程,描述了如何以一種邏輯性的、有組織的方法,... ......

    uj5u.com 2023-04-17 08:17:55 more
  • 計算機組成原理—存盤器

    計算機組成原理—硬體結構 二、存盤器 1.概述 存盤器是計算機系統中的記憶設備,用來存放程式和資料 1.1存盤器的層次結構 快取-主存層次主要解決CPU和主存速度不匹配的問題,速度接近快取 主存-輔存層次主要解決存盤系統的容量問題,容量接近與價位接近于主存 2.主存盤器 2.1概述 主存與CPU的聯 ......

    uj5u.com 2023-04-17 08:12:06 more