簡體   English   中英

如何將數據寫入緩沖區並使用第二個線程將緩沖區寫入二進制文件?

[英]How to write data into a buffer and write the buffer into a binary file with a second thread?

我正在從傳感器(相機)獲取數據並將數據寫入二進制文件。 問題在於它占用了磁盤上的大量空間。 因此,我使用了來自boost(zlib)的壓縮,並且空間減少了很多! 問題在於壓縮過程很慢,並且缺少大量數據。

因此,我想實現兩個線程,一個線程從相機獲取數據並將數據寫入緩沖區。 第二個線程將獲取緩沖區的前端數據並將其寫入二進制文件。 在這種情況下,所有數據都將存在。

如何實現此緩沖區? 它需要動態擴展和pop_front。 我應該使用std :: deque還是已經存在更好的東西了?

首先,您必須考慮以下四種速率(或速度):

  • 生產速度( SP ):傳感器每秒產生的平均字節數。
  • 壓縮速度( SC ):每秒可以壓縮的平均字節數。 這是壓縮算法的輸入字節數。
  • 壓縮率( RC ):您的compress算法產生的壓縮數據與未壓縮數據的平均比率(輸出與壓縮輸入的大小之比)(顯然介於0和1之間。)
  • 寫入速度( SW ):每秒可寫入磁盤的平均字節數。

如果SC小於SP ,則有麻煩。 這意味着您無法實時壓縮從傳感器收集的所有數據。 這意味着您最終將耗盡緩沖區內存。 您將必須找到更快的壓縮算法,或者將更多的CPU內核專用於壓縮。

如果SW小於SP乘以RC (壓縮后的傳感器數據大小),則您再次遇到麻煩。 這意味着您無法像生成和壓縮輸出數據一樣快地寫出輸出數據,而且,無論您有多少,最終都將耗盡緩沖區內存。 您可能可以通過采用更好的寫入策略或文件系統來獲得一定的速度,但是SW的真正收獲來自更好的磁盤系統(RAID,SSD,更好的硬件等)。

現在,如果一切正常,那么您可能可以采用以下架構來讀取,壓縮和寫出數據:

您將具有三個線程(或兩個,稍后將描述),每個線程分別處理管道的一部分。 您還將具有兩個線程安全隊列 ,一個用於從管道的每個階段到下一階段的通信。

假設兩個隊列分別命名為Q1Q2 ,則線程的高級操作將如下所示:

  1. 輸入線程:
    1. 讀取K字節的傳感器數據
    2. 將整個K字節作為單位放在Q1
    3. 轉到1。
  2. 壓縮線程:
    1. 等到Q1上有東西。
    2. Q1彈出一個數據緩沖區(可能是K字節)。
    3. 將緩沖區壓縮為希望更小的緩沖區,然后將其放在Q2
    4. 轉到1。
  3. 輸出線程:
    1. 等到Q2
    2. Q2彈出一個數據緩沖區。
    3. 將緩沖區寫入輸出文件。
    4. 轉到1。

工作中最消耗CPU的部分是在第二個線程中,而其他兩個線程可能不會占用很多CPU時間,因此可能可以共享一個CPU內核。 這意味着上述策略可以在兩個內核上運行。 但是,如果工作量很小或需要許多內核,它也可以在單個內核上運行。 這一切都取決於我上面描述的四個比率。

使用異步寫入(例如Windows上的IOCP或Linux上的epoll),您可以完全刪除第三個線程和第二個隊列。 然后,您的第二個線程需要執行以下操作:

  1. 等到Q1上有東西。
  2. Q1彈出一個數據緩沖區(可能是K字節)。
  3. 將緩沖區壓縮為希望更小的緩沖區。
  4. 向OS發出異步寫入請求,以將壓縮的緩沖區寫出到磁盤。
  5. 轉到1。

還有四個值得一提的問題:

  1. 應該選擇K以便與分配緩沖區,將其推入線程安全隊列並將其從線程安全隊列中彈出,開始壓縮運行以及向文件發出寫請求相關的各種(通常是恆定時間)活動所需的時間可以忽略不計。相對於實際工作(讀取傳感器數據,壓縮字節並寫入磁盤)。這通常意味着K必須盡可能大。 但是,如果K非常大(許多兆字節或幾百兆字節),那么如果您的應用程序崩潰,則會丟失很多數據。 您需要在性能和數據丟失風險之間找到平衡。 我建議(在不了解您的特定需求和約束的情況下) K的值應介於10KiB到1MiB之間。

  2. 如果您對並行/並行編程有一定的了解和經驗,那么實現線程安全隊列將很容易,但是如果您沒有並行/並行編程的知識和經驗,那么就很容易實現。 找到好的例子和實現並不難。 普通的std::dequestd::liststd::本身不能使用任何東西,但可以用作編寫線程安全隊列的良好基礎。

  3. 請注意,您正在排隊的是數據緩沖區 ,而不是單個數字或字節。 如果您一次通過該管道傳遞一個數字,那么它將非常緩慢且浪費。

  4. 某些壓縮算法在每次調用中可以使用多少數據方面受到限制,或者您必須在以后將每個對壓縮例程的調用與對解壓縮例程的調用同步輸出。 這些可能會影響K的選擇,以及寫入輸出文件的方式。 您可能必須添加一些元數據,以便以后能夠實際解壓縮並讀取數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM