jupyter內核崩潰

最近在做用k-mer評估基因組規模的任務,其中一個局部程序,想偷懶,直接在jupyter中跑了下結果,想看看這一小步處理如何,結果沒想到內核崩潰了!

這一步我的草稿代碼如下:

import pandas as pd
import glob
from pathlib import Path
def kmer_dict(jf_txt_file,top_m):"""Args:jf_txt_file (str): 主要是dump命令的輸出文件路徑top_m(int):從k-mer文件中要提取的top幾個k-merFun:從輸入文件中返回該k-mer文件中top M的k-mer的字典,key為k-mer,value為該k-mer的計數,按照count的降序整理,返回該dict,同時輸出為tsv格式的文件后續如果要使用輸出文件,可以繼續使用pandas等進行處理;如果要使用返回的字典變量,可以直接使用該函數的返回值  """kmer = pd.read_csv(jf_txt_file,sep=" ",header=None,names=["mer","count"])# 按照降序排列,順便只看前top_m行kmer = kmer.sort_values(by="count",ascending=False).head(top_m)# 輸出為tsv格式文件kmer.to_csv(jf_txt_file.replace(".txt",f"_{top_m}.tsv"),sep="\t",header=True)# 同時返回每一個k-mer的字典kmer_dict = dict(zip(kmer["mer"],kmer["count"]))return kmer_dict# 對于兩個基因組的所有k-mer文件,使用前面定義的kmer_dict函數來提取top M的k-mer字典
Q1_dir = "/data1/project/omics_final/Q1"
kmer_files = glob.glob(f"{Q1_dir}/*.txt")kmer_results = {}
for each_kmer in kmer_files:each_kmer_name = Path(each_kmer).stem  # 獲取文件名,不包含路徑和擴展名print(f"處理文件: {each_kmer_name}\n")# 此處對于每一個k-mer文件,提取其前10個對應的k-mer,并將結果輸出為對應的變量kmer_results[each_kmer_name] = kmer_dict(each_kmer,top_m=10)print(f"存儲為: kmer_results['{each_kmer_name}']\n")

做的事情呢,其實很簡單,就是用jellyfish count,在自己的測試基因組組裝數據集上統計了一下k-mer,

然后用jellyfish dump命令,將統計結果,用python稍微處理一下整理成字典形式,存到一個字典中;

我測試的數據只有2個新組裝的人類基因組,各自大小也就在3G左右,k-mer文件將近30個,每個大小不一,k小的文件才幾M,k大的文件組合花樣多,一般都幾十G,

任務是在jupyter中跑的,結果爆了,推測是處理大量k-mer數據導致的內存或計算資源耗盡。

問題來了:

我放在后臺跑,比如python xxx.py,肯定能夠成功執行,比放在cell中穩妥多了;

但是我的變量已經return出來了,我肯定還是想之后能夠直接在python環境中訪問的,雖然我用pandas再將結果文件讀進去都一樣的內容,但是太麻煩了,我太懶了。

有沒有什么一般的策略,不僅僅局限于這個問題,就是可能會導致內核崩潰的稍微大型計算任務,

我又想像放在后臺穩定運行一樣能夠跑完這個任務,又希望就放在cell中跑,跑完之后直接訪問結果變量?

法1:使用批處理 + 保存中間結果

其實就是很簡單,分批嘛,batch,我一次處理30多個數據多麻煩,每次只處理一小部分,比如說5個,如果還是太大了,就3個文件一處理;

重要的是我要及時將結果文件保存,所以還是輸出到硬盤上了(其實理論上來講,那我還是可以全部都放在后臺運行,然后在代碼上添加每一步都保存的命令,這樣我還是可以保證結果變量能夠訪問);

總之一小批一小批的運行并pickle輸出到硬盤中保存,然后下一次運行判斷哪些已經跑過了(這里比較重要,如果內核又崩潰了,我們就需要再次重啟內核在cell中跑,但是已經跑過的結果就不用再跑了)。

當然,有人會擔心如果我每次跑的時候,保存保存了一部分然后內核就崩潰了,那么文件系統檢查的時候如果重新加載了這個變量,然后它一看如果發現我加載的字典中已經有這個結果了,哪怕是一部分,會不會直接跳過,然后導致我其實這個應該被關注留意的結果其實并沒有得到重視?

比如說下面的這里?

其實這個問題我也考慮到了,所以我要確保每次保存結果的時候,都要完整保存或者說保存命令執行成功了,我才打印進程提醒:

比如說下面這里的進程——》

代碼整體邏輯如下:

import pandas as pd
import glob
import pickle
import os
from pathlib import Path
import gcdef kmer_dict(jf_txt_file, top_m):"""k-mer處理函數,添加錯誤處理"""try:print(f"  正在讀取文件: {jf_txt_file}")kmer = pd.read_csv(jf_txt_file, sep=" ", header=None, names=["mer", "count"])print(f"  數據形狀: {kmer.shape}")kmer = kmer.sort_values(by="count", ascending=False).head(top_m)# 輸出TSV文件output_file = jf_txt_file.replace(".txt", f"_{top_m}.tsv")kmer.to_csv(output_file, sep="\t", header=True, index=False)# 返回字典kmer_dict = dict(zip(kmer["mer"], kmer["count"]))# 清理內存del kmergc.collect()return kmer_dictexcept Exception as e:print(f"  處理文件 {jf_txt_file} 時出錯: {e}")return Nonedef process_kmer_files_safely():"""安全處理k-mer文件,支持斷點續傳"""Q1_dir = "/data1/project/omics_final/Q1"kmer_files = glob.glob(f"{Q1_dir}/*.txt")# 結果保存文件results_file = f"{Q1_dir}/kmer_results.pkl"# 如果已有結果文件,先加載if os.path.exists(results_file):print(f"加載已有結果: {results_file}")with open(results_file, 'rb') as f:kmer_results = pickle.load(f)print(f"已加載 {len(kmer_results)} 個結果")else:kmer_results = {}print(f"找到 {len(kmer_files)} 個txt文件")# 處理每個文件for i, each_kmer in enumerate(kmer_files, 1):each_kmer_name = Path(each_kmer).stem# 跳過已處理的文件if each_kmer_name in kmer_results:print(f"[{i}/{len(kmer_files)}] 跳過已處理文件: {each_kmer_name}")continueprint(f"[{i}/{len(kmer_files)}] 處理文件: {each_kmer_name}")try:result = kmer_dict(each_kmer, top_m=10)if result is not None:kmer_results[each_kmer_name] = resultprint(f"  成功處理,獲得 {len(result)} 個k-mer")# 每處理5個文件保存一次結果if i % 5 == 0:with open(results_file, 'wb') as f:pickle.dump(kmer_results, f)print(f"  已保存中間結果到: {results_file}")else:print(f"  處理失敗,跳過")except Exception as e:print(f"  發生異常: {e}")continue# 強制垃圾回收gc.collect()# 保存最終結果with open(results_file, 'wb') as f:pickle.dump(kmer_results, f)print(f"\n最終結果已保存到: {results_file}")print(f"總共處理了 {len(kmer_results)} 個文件")return kmer_results# 運行處理
try:kmer_results = process_kmer_files_safely()
except Exception as e:print(f"處理過程中發生錯誤: {e}")# 嘗試加載已保存的結果results_file = "/data1/project/omics_final/Q1/kmer_results.pkl"if os.path.exists(results_file):with open(results_file, 'rb') as f:kmer_results = pickle.load(f)print(f"加載了已保存的結果: {len(kmer_results)} 個文件")

真實運行情況:

所以3個還是消耗太大了,對于我上面的執行邏輯,干脆就直接改為1,每運行1次就保存,當然我還是得蹲在前臺一直看著這個代碼的運行。

文件其實很多,我們先仔細看一下:

ls -lh | awk -F " " '{print $5}' | grep "G" | awk -F "G" '{print $1}' | sort | uniq

可以發現,其實最大的文件已經達到了50G了,比基因組規模3G大了十幾倍,

其實運行了好幾次了,都是17-mer這個文件就一直卡著,其實我們也可以另外直接在shell中awk處理好輸出top M的文件,也沒必要什么都在python中處理,不然吃不消。

法2:使用Jupyter的后臺執行

# 在新的cell中運行
import threading
import timedef background_process():"""后臺處理函數"""global kmer_results  # 使用全局變量try:kmer_results = process_kmer_files_safely()print("后臺處理完成!")except Exception as e:print(f"后臺處理出錯: {e}")# 啟動后臺線程
processing_thread = threading.Thread(target=background_process)
processing_thread.daemon = True  # 設置為守護線程
processing_thread.start()print("后臺處理已啟動,您可以繼續使用其他cell")
print("使用 processing_thread.is_alive() 檢查處理狀態")

其實就是多線程庫threading的使用,主要函數繼承前面的,主要改了點運行

法3:分批處理 + 內存優化

其實batch的想法還是和1一樣的,只不過是多了個內存的監控強制優化

import pandas as pd
import glob
import pickle
from pathlib import Path
import gc
import psutil
import osdef get_memory_usage():"""獲取當前內存使用情況"""process = psutil.Process(os.getpid())return process.memory_info().rss / 1024 / 1024  # MBdef process_kmer_batch(file_batch, batch_num):"""處理一批文件"""print(f"\n=== 處理批次 {batch_num} ===")print(f"內存使用: {get_memory_usage():.1f} MB")batch_results = {}for i, file_path in enumerate(file_batch, 1):filename = Path(file_path).stemprint(f"  [{i}/{len(file_batch)}] 處理: {filename}")try:# 檢查內存使用memory_usage = get_memory_usage()if memory_usage > 4000:  # 超過4GB則強制清理print(f"    內存使用過高 ({memory_usage:.1f} MB),執行垃圾回收")gc.collect()result = kmer_dict(file_path, top_m=10)if result is not None:batch_results[filename] = resultprint(f"    成功,獲得 {len(result)} 個k-mer")except Exception as e:print(f"    失敗: {e}")continuereturn batch_resultsdef process_all_files_in_batches(batch_size=5):"""分批處理所有文件"""Q1_dir = "/data1/project/omics_final/Q1"kmer_files = glob.glob(f"{Q1_dir}/*.txt")print(f"總共找到 {len(kmer_files)} 個文件")print(f"將分 {len(kmer_files)//batch_size + 1} 批處理,每批 {batch_size} 個文件")all_results = {}# 分批處理for i in range(0, len(kmer_files), batch_size):batch = kmer_files[i:i+batch_size]batch_num = i//batch_size + 1batch_results = process_kmer_batch(batch, batch_num)all_results.update(batch_results)# 每批處理完后保存結果results_file = f"{Q1_dir}/kmer_results_batch_{batch_num}.pkl"with open(results_file, 'wb') as f:pickle.dump(batch_results, f)print(f"  批次結果已保存: {results_file}")# 強制垃圾回收gc.collect()print(f"  當前總結果數: {len(all_results)}")# 保存最終合并結果final_results_file = f"{Q1_dir}/kmer_results_final.pkl"with open(final_results_file, 'wb') as f:pickle.dump(all_results, f)print(f"\n處理完成!最終結果已保存: {final_results_file}")return all_results# 執行分批處理
kmer_results = process_all_files_in_batches(batch_size=3)

法4:訪問已保存的結果

這個其實就是最原始的想法,全都放在后臺,只保留全部運行之后的結果變量,執行過程當然是用到什么變量就得保存什么變量,還是保存為pkl格式。

當然,實際運行的時候,其實發現真的很耗費計算資源的任務,你放在cell中內核會崩潰,其實放在后臺則是會被kill,其實都是同樣有極大可能性失敗的;

# 在任何時候都可以加載已保存的結果
import pickle
import osdef load_saved_results():"""加載已保存的結果"""Q1_dir = "/data1/project/omics_final/Q1"# 嘗試加載最終結果final_file = f"{Q1_dir}/kmer_results_final.pkl"if os.path.exists(final_file):with open(final_file, 'rb') as f:results = pickle.load(f)print(f"加載最終結果: {len(results)} 個文件")return results# 如果沒有最終結果,嘗試加載中間結果intermediate_file = f"{Q1_dir}/kmer_results.pkl"if os.path.exists(intermediate_file):with open(intermediate_file, 'rb') as f:results = pickle.load(f)print(f"加載中間結果: {len(results)} 個文件")return resultsprint("沒有找到已保存的結果")return {}# 加載結果
kmer_results = load_saved_results()# 查看結果概況
if kmer_results:print(f"加載了 {len(kmer_results)} 個文件的結果")print("文件列表:")for name in sorted(kmer_results.keys()):print(f"  {name}: {len(kmer_results[name])} 個k-mer")

所以,如果僅僅只是簡單的文本文件處理,只要不涉及到非常復雜的數據處理,pandas能夠簡單應付的任務,還是直接用awk算了(也就是shell中批量處理得了)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909361.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909361.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909361.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java企業技術趨勢分析:AI應用的落地實踐與未來展望

Java企業技術趨勢分析:AI應用的落地實踐與未來展望 開篇:技術趨勢與市場需求 在當前快速發展的數字化時代,人工智能(AI)已經成為推動企業創新和效率提升的關鍵力量。Java作為企業級應用開發的主流語言,正…

每日Prompt:Steve Winter風格插畫

提示詞 世界攝影大師杰作,極簡主義,Steve Winter風格,6只不同顏色的布偶貓圍成一圈,看向鏡頭中心,仰天視角,天空背景,高品質細節,超精細CG,高分辨率,最佳品質…

Vue3 + Element Plus 獲取表格列信息

在 Vue 3 和 Element Plus 中,可以通過以下步驟獲取表格的列信息: 實現步驟: 使用 ref 綁定表格實例 通過表格實例的 store.states.columns 獲取列數據 處理列信息(過濾隱藏列、處理嵌套表頭等) 示例代碼&#xf…

logger2js - JavaScript日志與調試工具庫

logger2js - JavaScript日志與調試工具庫 logger2js是一個功能強大的前端JavaScript日志與調試工具庫,提供了豐富的日志輸出、性能測試和代碼調試功能。該庫支持配置化引入,包含5種皮膚風格和豐富的API接口,如 a l e r t 增強方法、 alert增…

Stone 3D使用RemoteMesh組件極大的縮小工程文件尺寸

Stone 3D的工程文件tsp默認包含了場景中所有的對象和數據,這樣的好處是tsp可以單獨離線保存,但壞處是tsp文件通常偏大。 解決這個問題的方法是把外部glb模型文件通過RemoteMesh組件來加載。 首先創建一個空實體,然后給該空實體添加RemoteMe…

【深入剖析】攻克 Java 并發的基石:Java 內存模型 (JMM) 原理與實踐指南

0.引言 理解 JMM (Java Memory Model - JMM) 是掌握 Java 并發編程的關鍵,它定義了多線程環境下,線程如何與主內存以及彼此之間交互內存數據。 核心目標: JMM 旨在解決多線程編程中的三個核心問題: 原子性 (Atomicity)&#xf…

【Three.js】初識 Three.js

Threejs介紹 我們開發 webgl 主要是使用 threejs 這個庫,因為 webGL太難用,太復雜!但是現代瀏覽器都支持WebGL,這樣我們就不必使用Flash、Java等插件就能在瀏覽器中創建三維圖形。 threejs 它提供-一個很簡單的關于WebGL特性的J…

【經驗總結】ECU休眠后連續發送NM報文3S后ECU網絡才被喚醒問題分析

目錄 前言 正文 1.問題描述 2.問題分析 3.驗證猜想 4.總結 前言 ECU的上下電/休眠喚醒在ECU開發設計過程中最容易出問題且都為嚴重問題,最近在項目開發過程中遇到ECU休眠狀態下連續發送NM報文3S后才能喚醒CAN網絡的問題,解決問題比較順利,但分析過程中涉及到的網絡休…

企業架構框架深入解析:TOGAF、Zachman Framework、FEAF與Gartner EA Framework

執行摘要 企業架構(EA)是一項至關重要的實踐,它使組織能夠協調其業務戰略、運營流程和技術基礎設施,以實現整體戰略目標。企業架構框架作為結構化的方法論和綜合性工具,旨在管理企業級系統的固有復雜性,提…

數字化動態ID隨機水印和ID跑馬燈實現教育視頻防錄屏

摘要:數字化動態ID隨機水印和ID跑馬燈技術可以有效保護數字教育資源。動態水印將用戶信息隨機顯示在視頻上且不可去除,能追蹤錄屏者并震懾盜版行為。ID跑馬燈則自定義顯示觀看者信息,便于追蹤盜版源頭并提供法律證據。這些技術大幅增加盜版成…

< 自用文兒 騰訊云 VPS > Ubuntu 24 系統,基本設置

前言: 3 月份買的騰訊云的這臺 VPS,剛發現現在退款,只能返回 0 元。測試應用已經遷移到JD,清除內容太麻煩,重裝更簡單。 因為配合政策,國內的云主機都有兩個 IP 地址,一個內網,一個…

React ajax中的跨域以及代理服務器

Axios的誕生 為什么會誕生Axios?說到Axios我們就不得不說下Ajax。最初的舊瀏覽器頁面在向服務器請求數據時,由于返回的是整個頁面的數據,所以整個頁面都會強制刷新一下,這對于用戶來講并不是很友好。因為當我們只需要請求部分數據…

HOT 100 | 73.矩陣置零、54.螺旋矩陣、48.旋轉圖像

一、73. 矩陣置零 73. 矩陣置零 - 力扣(LeetCode) 1. 解題思路 1. 使用兩個數組分別標記每行每列是否有0,初始化全為False,遇到0就變成True。 2. 遍歷矩陣,遇到0就將False改成True。 3. 再次遍歷矩陣,更…

神經網絡壓縮

網絡壓縮技術學習筆記 以下筆記基于提供的 PDF 文件(tiny_v7.pdf),總結了網絡壓縮技術的核心概念、實現原理和方法,特別針對多模態大模型、空間智能以及未來智能體(Agent)和通用人工智能(AGI&a…

論索引影響性能的一面④ 索引失蹤之謎【上】

梁敬彬梁敬弘兄弟出品 往期回顧 論索引影響性能的一面①索引的各種開銷 論索引影響性能的一面②索引的使用失效 論索引影響性能的一面③ 索引開銷與經典案例 開篇:DBA的深夜“尋人啟事” 作為數據庫的守護者,我們最信賴的伙伴莫過于“索引”。它如同一…

java集合(九) ---- Stack 類

目錄 九、Stack 類 9.1 位置 9.2 特點 9.3 棧 9.4 構造方法 9.5 常用方法 9.6 注意點:循環遍歷 Stack 類 九、Stack 類 9.1 位置 Stack 類位于 java.util 包下 9.2 特點 Stack 類是 Vector 類的子類Stack 類對標于數據結構中的棧結構 9.3 棧 定義&…

ARXML可視化轉換工具使用說明

ARXML可視化轉換工具 | 詳細使用指南與說明 📝 前言 自上篇文章《聊聊ARXML解析工具:我們是如何擺脫昂貴商業軟件的》發布以來,收到了眾多朋友的關注和咨詢,這讓我倍感榮幸! 新朋友請注意:如果您還沒有閱…

松勝與奧佳華按摩椅:普惠科技與醫療級體驗的碰撞

在智能健康設備快速普及的今天,按摩椅已從奢侈品轉變為家庭健康管理的重要工具。面對市場上琳瑯滿目的品牌,松勝與奧佳華憑借截然不同的發展路徑,各自開辟出特色鮮明的賽道:前者以“技術普惠”理念打破高端按摩椅的價格壁壘&#…

一起學習Web 后端——PHP(二):深入理解字符與函數的使用

一、前言 在上一講中,我們主要講PHP的相關知識。本節我們將繼續深入,學習: PHP 中各種語法字符、符號的含義與用法; PHP 中常用函數的種類、定義方式與實際應用。 這些知識是構建 Web 后端邏輯的基礎,對于后期編寫…

【Bluedroid】藍牙啟動之 GAP_Init 流程源碼解析

藍牙 GAP(通用訪問配置文件)模塊是藍牙協議棧的核心組件,負責設備發現、連接管理及基礎屬性暴露等關鍵功能。本文圍繞 Android藍牙協議棧 GAP 模塊的初始化流程與連接管理實現展開,結合代碼解析其核心函數(GAP_Init、gap_conn_init、gap_attr_db_init)的功能邏輯,以及關…