Operacje na tensorach odrzucają nieobsługiwane układy pamięci

Począwszy od platformy .NET 11 wielowymiarowe operacje kopiowania tensora i operacje przyjmujące miejsce docelowe odrzucają nieobsługiwane nakładające się układy pamięci za pomocą ArgumentException, zanim zapiszą dane wyjściowe. Konstruktory tensor-span weryfikują również typ elementu pamięci System.Array.

Zmiana jest dostarczana w pakiecie System.Numerics.Tensors, wraz z obsługiwanymi platformami docelowymi. Aktualizowanie pakietu może mieć wpływ na aplikacje przeznaczone dla wcześniejszych .NET wersji. Oddzielne TensorPrimitives interfejsy API zachowują istniejącą zasadę nakładania się.

Wersja wprowadzona

.NET 11

Poprzednie zachowanie

CopyTo, FlattenTo, TryCopyTo i TryFlattenTo udokumentowały obsługę nakładających się źródłowych i docelowych obszarów pamięci. Opisane metody Try traktowały źródło tak, jakby zostało ono najpierw skopiowane do magazynu tymczasowego.

Na przykład następujące źródło i miejsce docelowe odwołują się do nakładających się regionów tej samej tablicy:

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);

Udokumentowany kontrakt typu snapshot sugerował, że obiekt docelowy otrzyma [1, 2, 4, 5]. Rzeczywiste wyniki w przypadku nieobsługiwanego nakładania się mogą zależeć od układu i kolejności przechodzenia; implementacja nie spełniała tego kontraktu w sposób niezawodny.

Konstruktory, które przyjmowały System.Array, nie sprawdzały spójnie, czy typ elementu tablicy był zgodny z T.

Nowe zachowanie

Przykład zgłasza wyjątek ArgumentException przed skopiowaniem. To samo nieobsługiwane nakładanie jest również zgłaszane przez TryCopyTo i TryFlattenTo, gdy ich sprawdzenia kształtu i pojemności zakończą się powodzeniem.

Obsługiwane nakładanie się zależy od operacji:

Działanie Obsługiwane nakładanie
CopyTo i TryCopyTo Zwarte źródło i miejsce docelowe z równymi liczbami elementów lub dokładnie identycznymi widokami.
FlattenTo i TryFlattenTo Gęste źródło i rozpiętość docelowa.
Operacje na elementach przyjmujące parametr docelowy Identyczne widoki danych wejściowych/wyjściowych bez powtarzających się logicznych lokalizacji przechowywania. Przesunięte i nakładające się wejścia transmisji są odrzucane.
Tensor.ResizeTo Gęste źródło i cel. Nieobsługiwane nakładanie z krokiem jest odrzucane.
Przywrócenie do tego samego widoku Gęste odwrócenie w miejscu lub odwrócenie bez operacji.

Metody kopiowania Try nadal zwracają false, bez kopiowania, gdy miejsce docelowe jest zbyt krótkie. TryCopyTo zwraca false również wartość dla niezgodnych kształtów. Nieobsługiwane nakładanie się jest nieprawidłowym układem rozmieszczenia, a nie błędem związanym z pojemnością.

Tensor.ResizeTo i łączenie z istniejącym miejscem docelowym odrzuca wymiar o kroku zerowym, który zawiera więcej niż jeden element logiczny. Puste tablice docelowe i zerowe skoki w wymiarach pojedynczych pozostają dozwolone.

TensorSpan<T> i ReadOnlyTensorSpan<T> konstruktory przyjmujące System.Array rzucają wyjątek ArrayTypeMismatchException dla niezgodnych typów elementów tablicy. Zakresy tensorów z możliwością zapisu również odrzucają tablice kowariantne; zakresy tensorów tylko do odczytu zezwalają na kowariancję zgodnych typów referencyjnych.

Typ zmiany przełamującej

Jest to zmiana behawioralna.

Przyczyna zmiany

Poprawne kopie między dowolnie nakładającymi się tensorami o skokowym układzie pamięci mogą wymagać tymczasowego magazynu proporcjonalnego do całego tensoru. Jawne odrzucenie pozwala uniknąć uszkodzeń zależnych od przebiegu bez niejawnego alokowania migawek pełnych tensorów.

Powtarzające się lokalizacje magazynu danych wyjściowych nie mogą reprezentować odrębnych wyników logicznych. Sprawdzanie poprawności typu elementu tablicy uniemożliwia interpretowanie niezgodnej pamięci jako T i zapobiega zapisom za pośrednictwem kowariantnej pamięci tablicy.

Użyj nienakładającej się pamięci wyjściowej lub jawnie utwórz kopię źródła przed wykonaniem nakładającej się kopii. W poprzednim przykładzie:

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

Migawka zawiera element [1, 2, 4, 5]. W przypadku operacji elementowych z argumentem docelowym należy wykonać kopię każdych nakładających się danych wejściowych lub przydzielić oddzielny wynik. Zastąp docelowe miejsca nadawania niezależnie adresowalnymi magazynami wyjściowymi.

W przypadku rozpiętości tensora na System.Array podaj zgodny magazyn elementów. W przypadku widoku z możliwością zapisu użyj tablicy, która nie jest kowariantna, lub skopiuj elementy do nowego T[].

Nie zakładaj, że metoda kopiowania Try nie może zgłosić wyjątku. Wynik false oznacza niewystarczającą pojemność lub, w przypadku TryCopyTo, niezgodne kształty. Żaden przełącznik zgodności nie przywraca zachowania przy dowolnym nakładaniu się.

Interfejsy API, których dotyczy problem

Informacje dodatkowe