快捷方式

Tensor 基礎

支援 PyTorch 的 ATen Tensor 函式庫是一個簡單的 Tensor 函式庫,它直接在 C++17 中公開 Torch 中的 Tensor 運算。ATen 的 API 是從 PyTorch 使用的相同宣告自動產生,因此這兩個 API 會隨著時間相互追蹤。

Tensor 類型是動態解析的,因此 API 是通用的,不包含模板。也就是說,只有一種 Tensor 類型。它可以保存 CPU 或 CUDA Tensor,並且 Tensor 可能具有 Doubles、Float、Ints 等。這種設計使得編寫通用程式碼變得容易,而無需對所有內容進行模板化。

請參閱 https://pytorch.dev.org.tw/cppdocs/api/namespace_at.html#functions 以取得提供的 API。摘錄

Tensor atan2(const Tensor & other) const;
Tensor & atan2_(const Tensor & other);
Tensor pow(Scalar exponent) const;
Tensor pow(const Tensor & exponent) const;
Tensor & pow_(Scalar exponent);
Tensor & pow_(const Tensor & exponent);
Tensor lerp(const Tensor & end, Scalar weight) const;
Tensor & lerp_(const Tensor & end, Scalar weight);
Tensor histc() const;
Tensor histc(int64_t bins) const;
Tensor histc(int64_t bins, Scalar min) const;
Tensor histc(int64_t bins, Scalar min, Scalar max) const;

也提供就地運算,並且總是以後綴 _ 表示它們將修改 Tensor。

有效率地存取 Tensor 元素

當使用 Tensor 範圍的運算時,動態分派的相對成本非常小。但是,在某些情況下,尤其是在您自己的核心中,需要有效率的逐元素存取,並且逐元素迴圈內部的動態分派成本非常高。ATen 提供了存取器,這些存取器是透過單一動態檢查(檢查 Tensor 是否為該類型和維度數量)來建立的。然後,存取器公開一個 API,用於有效率地存取 Tensor 元素。

存取器是 Tensor 的暫時性檢視。它們僅在它們所檢視的 Tensor 的生命週期內有效,因此應僅在函式中本地使用,例如迭代器。

請注意,存取器與核心函數內的 CUDA Tensor 不相容。相反,您必須使用封裝的存取器,它的行為方式相同,但會複製 Tensor 元數據,而不是指向它。

因此,建議 CPU Tensor 使用存取器,CUDA Tensor 使用封裝的存取器

CPU 存取器

torch::Tensor foo = torch::rand({12, 12});

// assert foo is 2-dimensional and holds floats.
auto foo_a = foo.accessor<float,2>();
float trace = 0;

for(int i = 0; i < foo_a.size(0); i++) {
  // use the accessor foo_a to get tensor data.
  trace += foo_a[i][i];
}

CUDA 存取器

__global__ void packed_accessor_kernel(
    torch::PackedTensorAccessor64<float, 2> foo,
    float* trace) {
  int i = threadIdx.x;
  gpuAtomicAdd(trace, foo[i][i]);
}

torch::Tensor foo = torch::rand({12, 12});

// assert foo is 2-dimensional and holds floats.
auto foo_a = foo.packed_accessor64<float,2>();
float trace = 0;

packed_accessor_kernel<<<1, 12>>>(foo_a, &trace);

除了 PackedTensorAccessor64packed_accessor64 之外,還有對應的 PackedTensorAccessor32packed_accessor32,它們使用 32 位元整數進行索引。這在 CUDA 上可能會快很多,但可能會導致索引計算中的溢位。

請注意,模板可以包含其他參數,例如指標限制和用於索引的整數類型。有關存取器封裝的存取器的完整模板說明,請參閱文件。

使用外部建立的資料

如果您已經在記憶體(CPU 或 CUDA)中分配了 Tensor 資料,則可以在 ATen 中將該記憶體視為 Tensor

float data[] = { 1, 2, 3,
                 4, 5, 6 };
torch::Tensor f = torch::from_blob(data, {2, 3});

這些 Tensor 無法調整大小,因為 ATen 不擁有記憶體,但其他方面表現為正常 Tensor。

純量和零維張量

除了 Tensor 物件之外,ATen 也包含代表單一數字的 Scalar。與 Tensor 類似,Scalars 是動態型別的,並且可以保存任何一種 ATen 的數字型別。Scalars 可以從 C++ 數字型別隱式構造。之所以需要 Scalars,是因為有些函數(例如 addmm)會同時接受數字和 Tensors,並期望這些數字與 tensor 具有相同的動態型別。它們也用於 API 中,以指示函數*總是*會返回 Scalar 值的地方,例如 sum

namespace torch {
Tensor addmm(Scalar beta, const Tensor & self,
             Scalar alpha, const Tensor & mat1,
             const Tensor & mat2);
Scalar sum(const Tensor & self);
} // namespace torch

// Usage.
torch::Tensor a = ...
torch::Tensor b = ...
torch::Tensor c = ...
torch::Tensor r = torch::addmm(1.0, a, .5, b, c);

除了 Scalar 之外,ATen 也允許 Tensor 物件為零維。這些 Tensors 保存單一值,並且可以是較大 Tensor 中單一元素的參考。它們可以用於任何期望 Tensor 的地方。它們通常由像 select 這樣的運算子創建,這些運算子會減少 Tensor 的維度。

torch::Tensor two = torch::rand({10, 20});
two[1][2] = 4;
// ^^^^^^ <- zero-dimensional Tensor

文件

存取 PyTorch 的完整開發者文件

查看文件

教學

取得初學者和高級開發人員的深入教學

查看教學

資源

尋找開發資源並取得問題解答

查看資源