張量運算不支援的儲存配置會被拒絕

從 .NET 11 開始,多維張量複製與接受目的地參數的操作會以 ArgumentException 拒絕不支援的重疊儲存配置,並在寫入輸出之前進行。 Tensor-span 建構子也會驗證 System.Array 儲存體的元素類型。

此變更已在 System.Numerics.Tensors 套件中提供,包含其支援的目標框架。 更新套件可能會影響針對較早期 .NET 版本的應用程式。 這些獨立 TensorPrimitives 的 API 保留其現有的重疊規範。

所推出的版本

.NET 11

以前的行為

CopyTo、FlattenTo、TryCopyTo 和 TryFlattenTo 記錄了對重疊來源與目的地儲存的支援。 這些 Try 方法會將來源視為已先複製到暫存儲存後再處理。

例如,以下來源與目的位置指的是同一陣列中重疊的區域:

int[] storage = { 1, 2, 3, 4, 5, 6 };
ReadOnlyTensorSpan<int> source = new(storage, new nint[] { 2, 2 }, new nint[] { 3, 1 });
TensorSpan<int> destination = new(storage, new nint[] { 2, 2 });
source.CopyTo(destination);

該快照式合約表示目標端會收到 [1, 2, 4, 5]。 未支援重疊的實際結果可能取決於佈局與遍歷順序;但實作未能穩定達成該約定。

採用 System.Array 的建構子未一致地驗證陣列元素類型是否與 T 相容。

新行為

範例先拋 ArgumentException 出再複製。 同樣的不受支援的重疊也會由 TryCopyTo 和 TryFlattenTo 擲回,當它們的形狀和容量檢查成功時。

支援的重疊仍依作業而異:

作業 支援重疊功能
CopyTo 與 TryCopyTo 來源與目的地皆為密集且元素數量相等,或兩個視圖完全相同。
FlattenTo 與 TryFlattenTo 密集的來源與目的端範圍。
接受目標的逐元素操作 輸入/輸出視圖相同,且沒有重複的邏輯儲存位置。 位移後的重疊及廣播輸入重疊則被拒絕。
Tensor.ResizeTo 密集來源與目的地。 不支援的步幅重疊則被拒絕。
反轉至同一檢視 密集型原地反轉,或稱 no-op 反轉。

Try當目標緩衝區太短時,複製方法仍會返回 false,但不會複製。 TryCopyTo 對於不相容的形狀也會傳回 false。 未支援的重疊是無效的佈局,而非容量不足錯誤。

Tensor.ResizeTo 以及連接到現有目的地的操作會拒絕包含多個邏輯元素的零步幅維度。 空置目的地和單一維度中的零步幅仍然被允許。

接受 System.Array 的 TensorSpan<T> 和 ReadOnlyTensorSpan<T> 建構子會因不相容的陣列元素類型而擲回 ArrayTypeMismatchException。 可寫入張量範圍也會拒絕協變陣列;唯讀張量範圍允許相容參考型別的協變。

破壞性變更的類型

這是一種 行為改變。

變更原因

在任意重疊的具步幅的張量之間進行正確複製,可能需要與整個張量成正比的暫時儲存空間。 顯式拒絕避免遍歷依賴的損壞,而不會默默分配全張量快照。

重複的輸出儲存位置無法代表不同的邏輯結果。 陣列元素類型驗證防止不相容的儲存被解讀為 T,並防止透過協變陣列儲存寫入。

使用非重疊的輸出儲存區,或在進行重疊複製前,明確地先建立來源快照。 針對上述範例:

int[] snapshot = new int[checked((int)source.FlattenedLength)];
source.FlattenTo(snapshot);
ReadOnlyTensorSpan<int> independentSource = new(snapshot, source.Lengths);
independentSource.CopyTo(destination);

快照包含 [1, 2, 4, 5]。 對於以目標為參數的逐元素運算,請對每個重疊的輸入建立快照,或分配一個獨立結果。 以獨立可尋址的輸出儲存取代廣播目的地。

對於 System.Array 上的張量範圍,提供相容的元素儲存。 若要使用可寫入的檢視,請使用非協變的陣列,或將元素複製到新的 T[]。

不要以為 Try 複製方法不會引發例外。 false 結果表示容量不足,或對於 TryCopyTo 而言不相容的形狀。 沒有任何相容性切換可恢復任意重疊行為。

受影響的 API

也請參閱