PyTorch常用Tensor形狀變換函數詳解

PyTorch常用Tensor形狀變換函數詳解

在PyTorch中,對張量(Tensor)進行形狀變換是深度學習模型構建中不可或缺的一環。無論是為了匹配網絡層的輸入要求,還是為了進行數據預處理和維度調整,都需要靈活運用各種形狀變換函數。本文將系統介紹幾個核心的形狀變換函數,并深入剖析它們的用法區別與關鍵點。

一、改變形狀與元素數量:view()reshape()

view()reshape() 是最常用的兩個用于重塑張量形狀的函數。它們都可以改變張量的維度,但前提是新舊張量的元素總數必須保持一致。盡管功能相似,但它們在工作機制上存在關鍵差異。

view()

view() 函數返回一個具有新形狀的張量,這個新張量與原始張量 共享底層數據。這意味著修改其中一個張量的數據,另一個也會隨之改變。

關鍵點:

  • 內存共享view() 保證返回的張量與原張量共享數據,不會創建新的內存副本,因此效率很高。
  • 連續性要求view() 只能作用于在內存中 連續 (contiguous) 的張量。對于一個非連續的張量(例如通過 transpose 操作后得到的張量),直接使用 view() 會引發錯誤。 在這種情況下,需要先調用 .contiguous() 方法將其變為連續的,然后再使用 view()
reshape()

reshape() 函數同樣用于改變張量的形狀,但它更加靈活和安全。

關鍵點:

  • 智能處理reshape() 可以處理連續和非連續的張量。
  • 視圖或副本:當作用于連續張量時,reshape() 的行為類似于 view(),返回一個共享數據的視圖。 然而,當作用于非連續張量時,reshape() 會創建一個新的、具有所需形狀的連續張量,并復制原始數據,此時返回的是一個副本,與原張量不再共享內存。
  • 不確定性reshape() 的語義是它 可能 會也 可能不會 共享存儲空間,事先無法確定。
用法區別與選擇
特性view()reshape()
內存共享總是共享(返回視圖)可能共享(視圖),也可能不共享(副本)
對非連續張量拋出錯誤自動創建副本
推薦使用場景當確定張量是連續的,并且需要保證內存共享以提升效率時。當不確定張量的連續性,或希望代碼更健干時,reshape() 是更安全的選擇。
使用示例
import torch# 創建一個連續的張量
x = torch.arange(12)  # tensor([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])# 使用 view() 和 reshape()
x_view = x.view(3, 4)
x_reshape = x.reshape(3, 4)print("Original is contiguous:", x.is_contiguous()) # True
print("x_view:\n", x_view)
print("x_reshape:\n", x_reshape)# 創建一個非連續的張量
y = torch.arange(12).reshape(3, 4).t() # .t() 是 transpose(0, 1) 的簡寫
print("\nOriginal y is contiguous:", y.is_contiguous()) # False# 對非連續張量使用 reshape() - 成功
y_reshape = y.reshape(3, 4)
print("y_reshape:\n", y_reshape)
print("y_reshape is contiguous:", y_reshape.is_contiguous()) # True# 對非連續張量使用 view() - 報錯
try:y_view = y.view(3, 4)
except RuntimeError as e:print("\nError with view():", e)# 先用 .contiguous() 再用 view() - 成功
y_view_contiguous = y.contiguous().view(3, 4)
print("y_view_contiguous:\n", y_view_contiguous)

二、交換維度:transpose()permute()

reshapeview 不同,transposepermute 用于重新排列張量的維度,而不是像“拉伸”或“壓縮”數據那樣改變形狀。

transpose()

transpose() 函數專門用于 交換 張量的兩個指定維度。

用法: tensor.transpose(dim0, dim1)

關鍵點:

  • 兩兩交換:每次只能交換兩個維度。
  • 共享數據:返回的張量與原張量共享底層數據,但通常會導致張量在內存中變為非連續。
permute()

permute() 函數則提供了更強大的維度重排能力,可以一次性對所有維度進行任意順序的重新排列。

用法: tensor.permute(dims),其中 dims 是一個包含所有原始維度索引的新順序。

關鍵點:

  • 任意重排:必須為所有維度提供新的順序。
  • 通用性transpose(dim0, dim1) 可以看作是 permute 的一個特例。
  • 共享數據與非連續性:同樣地,permute 返回的也是一個共享數據的視圖,并且通常會使張量變為非連續。
用法區別與選擇
  • 當只需要交換兩個維度時,使用 transpose() 更直觀。
  • 當需要進行更復雜的維度重排,例如將 (B, C, H, W) 變為 (B, H, W, C) 時,必須使用 permute()

重要提示:由于 transpose()permute() 經常產生非連續的張量,如果后續需要使用 view(),必須先調用 .contiguous() 方法。

使用示例
import torch# 假設張量形狀為 (batch, channel, height, width)
x = torch.randn(2, 3, 4, 5) # Shape: [2, 3, 4, 5]# 使用 transpose() 交換 height 和 width 維度
# 原始維度: 0, 1, 2, 3 -> 交換維度 2 和 3
x_transposed = x.transpose(2, 3)
print("Original shape:", x.shape) # torch.Size([2, 3, 4, 5])
print("Transposed shape:", x_transposed.shape) # torch.Size([2, 3, 5, 4])# 使用 permute() 將 (B, C, H, W) 變為 (B, H, W, C)
# 原始維度: 0, 1, 2, 3 -> 新維度順序: 0, 2, 3, 1
x_permuted = x.permute(0, 2, 3, 1)
print("Permuted shape:", x_permuted.shape) # torch.Size([2, 4, 5, 3])

三、增減維度:unsqueeze()squeeze()

這兩個函數用于添加或移除長度為 1 的維度,這在處理批處理數據或需要廣播時非常有用。

unsqueeze()

unsqueeze() 用于在指定位置 添加 一個長度為 1 的維度。

用法: tensor.unsqueeze(dim)

關鍵點:

  • 它會在 dim 參數指定的位置插入一個新維度。
  • 常用于為單個樣本數據添加 batch 維度,或為二維張量添加 channel 維度,以符合模型的輸入格式。
squeeze()

squeeze() 用于 移除 所有長度為 1 的維度。

用法:

  • tensor.squeeze(): 移除所有長度為 1 的維度。
  • tensor.squeeze(dim): 只在指定 dim 位置移除長度為 1 的維度,如果該維度長度不為 1,則張量不變。

關鍵點:

  • 這是一個降維操作,可以方便地去除多余的、長度為1的維度。
  • unsqueeze()squeeze() 互為逆操作。
  • 返回的張量同樣與原張量共享數據。
使用示例
import torch# 創建一個形狀為 (3, 4) 的張量
x = torch.randn(3, 4)
print("Original shape:", x.shape) # torch.Size([3, 4])# 使用 unsqueeze() 在第 0 維添加 batch 維度
x_unsqueezed_0 = x.unsqueeze(0)
print("Unsqueeze at dim 0:", x_unsqueezed_0.shape) # torch.Size([1, 3, 4])# 使用 unsqueeze() 在第 1 維添加 channel 維度
x_unsqueezed_1 = x.unsqueeze(1)
print("Unsqueeze at dim 1:", x_unsqueezed_1.shape) # torch.Size([3, 1, 4])# --- squeeze ---
y = torch.randn(1, 3, 1, 4)
print("\nOriginal y shape:", y.shape) # torch.Size([1, 3, 1, 4])# 使用 squeeze() 移除所有長度為 1 的維度
y_squeezed_all = y.squeeze()
print("Squeeze all ones:", y_squeezed_all.shape) # torch.Size([3, 4])# 使用 squeeze(dim) 只移除指定位置的維度
y_squeezed_dim = y.squeeze(0) # 移除第 0 維
print("Squeeze at dim 0:", y_squeezed_dim.shape) # torch.Size([3, 1, 4])

四、view/reshapesqueeze/unsqueeze 的關系:可替代性討論

從最終的形狀結果來看,viewreshape 在很多情況下確實可以實現與 squeezeunsqueeze 相同的效果。然而,它們的設計理念和使用場景存在顯著差異,一般不建議混用。

使用 reshape 替代 unsqueeze

將一個形狀為 (A, B) 的張量通過 unsqueeze(0) 變為 (1, A, B),可以等價地使用 reshape(1, A, B) 來實現。

關鍵區別:

  • 可讀性與意圖unsqueeze(dim) 的意圖非常明確——在指定位置插入一個新維度。這使得代碼更易于理解。而 reshape() 需要提供完整的最終形狀,閱讀者需要通過對比新舊形狀才能理解其操作意圖。
  • 便利性:使用 unsqueeze 時,無需知道張量的其他維度尺寸。而使用 reshape,則必須知道所有維度的大小才能構建新的形狀參數。
使用 reshape 替代 squeeze

將一個形狀為 (1, A, B, 1) 的張量通過 squeeze() 變為 (A, B),可以等價地使用 reshape(A, B) 實現。

關鍵區別:

  • 自動化與便利性squeeze() 的核心優勢在于其自動化。它會自動移除所有大小為 1 的維度,使用者無需預先知道哪些維度是 1。如果使用 reshape,則必須手動計算出目標形狀,這在處理動態或未知的輸入形狀時會非常繁瑣。
  • 條件性操作squeeze(dim) 只在指定維度大小為 1 時才執行操作,否則張量保持不變。reshape 不具備這種條件判斷能力,它會強制改變形狀,如果元素總數不匹配則會報錯。

雖然 reshape 功能更強大,理論上可以模擬 squeezeunsqueeze 的操作,但強烈建議使用專用的函數

  • 當你的意圖是添加或移除單個維度時,請使用 unsqueezesqueeze。這不僅使代碼更清晰、更具可讀性,還能利用 squeeze 的自動檢測和條件操作特性,讓代碼更健壯。
  • 只有當你需要進行更復雜的、非增減單一維度的形狀重塑時,才應使用 reshapeview
使用示例
import torch# --- unsqueeze vs reshape ---
x = torch.randn(3, 4) # Shape: [3, 4]# 目標: 添加 batch 維度 -> (1, 3, 4)
x_unsqueezed = x.unsqueeze(0)
x_reshaped = x.reshape(1, 3, 4)print("Unsqueeze result:", x_unsqueezed.shape) # torch.Size([1, 3, 4])
print("Reshape result:", x_reshaped.shape)   # torch.Size([1, 3, 4])
# 結果相同,但 unsqueeze(0) 意圖更明確# --- squeeze vs reshape ---
y = torch.randn(1, 3, 1, 4) # Shape: [1, 3, 1, 4]# 目標: 移除所有大小為1的維度 -> (3, 4)
y_squeezed = y.squeeze()
y_reshaped = y.reshape(3, 4) # 需要手動知道結果是 (3, 4)print("\nSqueeze result:", y_squeezed.shape) # torch.Size([3, 4])
print("Reshape result:", y_reshaped.shape)   # torch.Size([3, 4])
# squeeze() 自動完成,reshape() 需要手動計算

五、復制與擴展數據:repeat()expand()

除了改變張量的形狀,有時還需要沿著某些維度復制數據,以生成一個更大的張量。repeat()expand() 函數都可以實現這一目的,但它們在實現方式和內存使用上有本質的區別。

expand()

expand() 函數通過擴展長度為 1 的維度來創建一個新的、更高維度的張量 視圖。它并不會實際分配新的內存來存儲復制的數據,因此非常高效。

關鍵點:

  • 內存高效expand() 返回的是一個視圖,與原張量共享底層數據,不產生數據拷貝。
  • 參數含義expand() 的參數指定的是張量的 最終目標形狀
  • 使用限制expand() 只能用于擴展大小為 1 的維度(也稱為“單例維度”)。對于大小不為 1 的維度,新尺寸必須與原尺寸相同。如果想保持某個維度不變,可以傳入 -1 作為該維度的尺寸。
repeat()

repeat() 函數通過在物理內存中 真正地復制 數據來構造一個新張量。它會沿著指定的維度將張量重復指定的次數。

關鍵點:

  • 數據拷貝repeat() 會創建一個全新的張量,其內容是原張量數據的重復,因此內存占用會相應增加。
  • 參數含義repeat() 的參數指定的是每個維度需要 重復的次數
  • 無限制repeat() 可以對任意維度的張量進行重復,無論其原始大小是否為 1。
用法區別與選擇
特性expand()repeat()
內存使用高效,不分配新內存(返回視圖)內存消耗大,會創建數據的完整副本
參數含義擴展后的 目標尺寸每個維度的 重復次數
使用限制只能擴展大小為 1 的維度可以重復任意大小的維度
推薦使用場景當需要進行廣播(Broadcasting)操作且注重內存效率時,例如將一個偏置向量擴展以匹配一個批次的數據。當需要一個獨立的、數據重復的張量副本,并且后續可能需要就地修改其中的部分數據時。
使用示例
import torch# 創建一個包含單例維度的張量
x = torch.tensor([[1], [2], [3]]) # Shape: [3, 1]
print("Original tensor x:\n", x)
print("Original shape:", x.shape)# 使用 expand() 將大小為 1 的維度擴展到 4
# 目標形狀是 (3, 4),-1 表示該維度大小不變
expanded_x = x.expand(-1, 4)
print("\nExpanded x shape:", expanded_x.shape) # torch.Size([3, 4])
print("Expanded x:\n", expanded_x)# 使用 repeat() 實現類似效果
# 維度0重復1次(不變),維度1重復4次
repeated_x = x.repeat(1, 4)
print("\nRepeated x (1, 4) shape:", repeated_x.shape) # torch.Size([3, 4])
print("Repeated x (1, 4):\n", repeated_x)# 使用 repeat() 進行更復雜的復制
# 維度0重復2次,維度1重復3次
complex_repeated_x = x.repeat(2, 3)
print("\nRepeated x (2, 3) shape:", complex_repeated_x.shape) # torch.Size([6, 3])
print("Repeated x (2, 3):\n", complex_repeated_x)# expand() 無法作用于大小不為1的維度
try:# 嘗試將大小為3的維度擴展到6,會報錯x.expand(6, 4)
except RuntimeError as e:print("\nError with expand():", e)

六、組合技巧:先升維再擴展

在實際應用中,一個常見的需求是將一個一維向量復制多次,以構建一個二維矩陣。例如,將一個權重向量應用到批次中的每一個樣本上。這個操作可以通過組合“升維”和“擴展/復制”函數來高效實現。這里介紹兩種主流的組合方法:view/expandreshape/repeat

方法一:view/reshape + expand (內存高效)

這個組合利用了 expand 函數不復制數據、只創建視圖的特性,是實現廣播操作的首選。

  1. 升維:首先,使用 view(1, -1)reshape(1, -1) (或者更直觀的 unsqueeze(0)) 將一維向量 (N) 變為二維的行向量 (1, N)
  2. 擴展:然后,調用 expand(M, -1)。這會將大小為 1 的第 0 維“擴展” M 次,得到一個 (M, N) 的張量。-1 表示該維度的大小保持不變。

關鍵點:

  • 整個過程沒有發生數據拷貝,返回的是一個共享原始數據的視圖,內存效率極高。
  • 由于返回的是視圖,并且多個位置共享同一塊內存,因此不適合對結果進行就地修改(in-place modification)。
方法二:reshape/view + repeat (數據獨立)

這個組合會創建數據的完整物理副本,適用于需要一個獨立的、可修改的新張量的場景。

  1. 升維:與方法一相同,先將一維向量 (N) 變為 (1, N)
  2. 復制:然后,調用 repeat(M, 1)。這會將張量在第 0 維上復制 M 次,在第 1 維上復制 1 次(即不復制),最終得到一個 (M, N) 的張量。

關鍵點:

  • repeat 會實際分配新的內存并復制數據,生成的新張量與原始張量完全獨立。
  • 內存開銷是 M * N,但好處是你可以自由地修改新張量中的任何元素,而不會影響原始數據。
對比與選擇
特性view/reshape + expandreshape/view + repeat
內存使用高效,共享數據,不創建副本消耗大,創建完整的數據副本
數據獨立性不獨立,是原始數據的視圖完全獨立,是全新的張量
修改數據通常不應修改,可能會導致錯誤可以自由、安全地修改
推薦場景廣播、只讀操作、對內存敏感的場景需要一個可修改的、數據獨立的副本時
使用示例
import torch# 1. 創建一個初始的一維向量
x = torch.arange(4) # tensor([0, 1, 2, 3]), Shape: [4]
num_repeats = 3
print(f"Original 1D tensor: {x}\n")# --- 方法一: reshape + expand (內存高效) ---
# 先升維 (4) -> (1, 4),再擴展 (1, 4) -> (3, 4)
x_expanded = x.reshape(1, -1).expand(num_repeats, -1)
print("--- reshape + expand ---")
print("Expanded shape:", x_expanded.shape)
print("Expanded tensor:\n", x_expanded)
# 注意:x_expanded 與 x 共享內存# --- 方法二: reshape + repeat (數據獨立) ---
# 先升維 (4) -> (1, 4),再復制 (1, 4) -> (3, 4)
x_repeated = x.reshape(1, -1).repeat(num_repeats, 1)
print("\n--- reshape + repeat ---")
print("Repeated shape:", x_repeated.shape)
print("Repeated tensor:\n", x_repeated)# 驗證數據獨立性
# 修改 repeated tensor 的一個元素
x_repeated[0, 1] = 99
print("\nModified repeated tensor:\n", x_repeated)
print("Original tensor after modifying repeated:", x) # 原始張量不受影響# 嘗試修改 expanded tensor 會引發問題,因為它是一個視圖
try:x_expanded[0, 1] = 99
except RuntimeError as e:print(f"\nError modifying expanded tensor: {e}")

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

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

相關文章

自主智能Agent如何重塑工作流自動化:技術、經濟與未來展望

自主智能Agent的崛起與工作流自動化的范式革命2025年7月,當OpenAI向付費用戶推出具備網頁瀏覽和代碼執行能力的ChatGPT Agent時,工作流自動化領域迎來了一場靜默但徹底的革命。這款不再滿足于簡單問答的智能體,在一個安全的虛擬計算機環境中運…

技術架構、行業應用、工具鏈整合、挑戰應對及未來趨勢五大模塊,引用多個權威來源數據與開源項目實現細節。

以下是一份關于AI技術落地的實戰經驗總結報告,結合代碼示例、可視化圖表與行業案例,內容分為技術架構、行業應用、工具鏈整合、挑戰應對及未來趨勢五大模塊,引用多個權威來源數據與開源項目實現細節。AI技術落地實戰指南:從架構設…

第 9 篇:神經網絡初探——當AI擁有了“大腦”,世界從此不同

《人工智能AI之機器學習基石》系列⑨ 專欄核心理念: 用通俗語言講清楚機器學習的核心原理,強調“洞察 + 技術理解 + 應用連接”,構建一個完整的、富有啟發性的知識體系。

音頻焦點 Android Audio Focus 進階

舊焦點處理 示例調用鏈: requestAudioFocus() → propagateFocusLossFromGain_syncAf() → handleFocusLossFromGain()。 系統事件(如來電)→ 強制焦點變化 → handleFocusLossFromGain()。 函數 propagateFocusLossFromGain_syncAf 焦點持有者發生的焦點丟失通知 主要功能…

MFC UI對話框

文章目錄對話框模態對話框創建銷毀關閉CDialog::OnCancel()EndDialog()CDialog::DestroyWindow()非模態對話框創建銷毀關閉delete this對話框 模態對話框 ??阻塞父窗口??,強制用戶先處理對話框。關閉前父窗口無法響應事件。 創建 推薦:非指針方式…

RabbitMQ--@RabbitListener及@RabbitHandle

兩者區別 在 Spring AMQP 中,RabbitListener 和 RabbitHandler 是處理 RabbitMQ 消息的核心注解,但職責和使用場景完全不同。以下從 定義、區別、場景、示例 逐層解析:一、核心定義1. RabbitListener作用:標記 方法或類 為 Ra…

【基于CKF的IMM】MATLAB例程,CV和CT兩個模型下的IMM,二維,濾波使用CKF(容積卡爾曼濾波),附下載鏈接

本程序實現了基于交互多模型(IMM)容積卡爾曼濾波(CKF)的多模型融合定位方法,并與純CV?CKFCV-CKFCV?CKF(勻速模型)和CT?CKFCT-CKFCT?CKF(勻角速度轉彎模型)方法對比。…

AI資訊日報 - 2025年07月28日

AI資訊日報 | 2025年07月28日 周一 今日核心要點 精華提煉 技術突破 ? 騰訊混元:開源發布、3D技術 ? 書生Intern:開源發布、多模態 企業動態 ? AI工具集:協同創作、視頻生成 數據概覽分類數量重點關注技術突破2 條開源發布、3D技術企業動態…

大語言模型 LLM 通過 Excel 知識庫 增強日志分析,根因分析能力的技術方案(1):總體介紹

文章大綱 1. 核心目標 2. 系統總體架構 3. Google Cloud 端到端方案(含無 RAG & RAG 雙模式) 3.1 無 RAG:Function-Calling 查表模式 3.2 RAG:托管式向量檢索 4. 開源輕量級方案 5. 數字孿生聯合驗證(實驗性) 6. 知識圖譜增強(Neo4j) 7. 監控與持續優化(CometLLM)…

Deepseek + browser-use 輕松實現瀏覽器自動化

在數字化時代,瀏覽器應用廣泛,瀏覽器自動化可大幅提升效率。Deepseek 是強大的智能語言模型,能精準解析復雜指令,browser - use 是專注瀏覽器操作的工具,提供豐富 API 接口,支持主流瀏覽器的各類自動化操作…

開疆智能ModbusTCP轉Profient網關連接西門子PLC與川崎機器人配置案例

本案例是西門子PLC與川崎機器人通過Profient轉ModbusTCP網關進行通訊轉換的配置案例,西門子作為profinet主站,機器人作為ModbusTCP服務器。配置過程:機器人配置川崎機器人控制器提供了RS232、以太網的通信接口,同時也可通過加裝選…

Docker多主機網絡連接:實現跨主機通信

Docker 是一種流行的容器化平臺,它可以幫助開發人員更方便地構建、發布和管理應用程序。在 Docker 中,容器是獨立運行的應用程序包裝,包含了運行所需的所有文件、庫和環境變量。Docker 提供了多種網絡連接方式,使得容器之間可以進…

OSPF筆記

一、OSPF基礎1、技術背景(RIP中存在的問題)RIP中存在最大跳數為15的限制,不能適應大規模組網周期性發送全部路由信息,占用大量的帶寬資源路由收斂速度慢以跳數作為度量值存在路由環路可能性每隔30秒更新2、OSPF協議特點沒有跳數限…

kotlin基礎【3】

Kotlin Playground: Edit, Run, Share Kotlin Code Online 資料&#xff1a;kotlin實戰 第一章 data class Person(val name: String,val age:Int?null)//允許接受以age為空&#xff0c;當為空將它賦值為null,如果不這么寫直接寫age:Int?是否可以fun main(args:Array<St…

Java-數構二叉樹

1.樹 1.1概念 樹是一種非線性的數據結構&#xff0c;它是由n個有限節點組成一個具有層次關系。這種結構有以下特點&#xff1a; 一個特殊的結點&#xff0c;稱為根節點&#xff0c;根節點沒有前驅節點除根節點以外&#xff0c;其余節點分成M個互不相交的集合。每個集合又是一…

編程中水合的理解

在編程中&#xff0c;水合&#xff08;Hydration&#xff09; 是一個常見概念&#xff0c;尤其在 前端開發 和 服務端渲染&#xff08;SSR&#xff09; 場景中頻繁出現。它的核心含義是&#xff1a;將靜態內容“激活”為交互式動態內容。1. 水合的本質簡單理解&#xff1a;水合…

使用ffmpeg轉碼h265后mac默認播放器不支持問題

由于mac自帶錄屏是mov并且文件特別大&#xff0c;我使用ffmpeg轉碼視頻為h265使用如下命令ffmpeg_command [ffmpeg_path,"-i", input_path,"-c:v", "libx265","-preset", "veryslow","-map_metadata", "0&q…

支持MySQL、PostgreSQL和Redis集群部署,1Panel開源面板v2.0.5版本發布

2025年7月24日&#xff0c;現代化、開源的Linux服務器運維管理面板1Panel正式發布v2.0.5版本。在這一版本中&#xff0c;1Panel新增數據庫集群部署、郵件告警和主從節點靈活切換三項功能&#xff0c;聚焦為企業級運維場景提供更優使用體驗。 1Panel v2.0.5版本是1Panel開源面板…

GaussDB 數據庫架構師修煉(九) 邏輯備份實操

1 邏輯備份定義 邏輯備份是指與業務有關的對象進行備份&#xff0c;這個對象包括表、表的數據、視圖、索引、過程、函數等等。GaussDB支持邏輯備份的工具為gs_dump、gs_restore&#xff0c;以下舉例說明。 2 創建舉例數據 以下創建testdb庫&#xff0c;創建test1模式&#xf…

c# Winform發布成獨立文件

改造前&#xff1a; 通過發布頁面&#xff0c;修改部署模式為獨立&#xff0c;輸出文件目錄沒有完全包含所有dll改造后&#xff1a;通過修改項目文件方式修改csproj前&#xff1a;<PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net…