Assignment 01: Tensors and Einsum
In this assignment you will implement several tensor operations from scratch using Python and PyTorch tensors. All code should be written in src/assignment_01.py. Starter code with vector/tensor initializations, function headers, and assertion-based tests is already provided. Please do not modify the test code.
Task 1: Dot Product
The dot product of two vectors $\mathbf{a}, \mathbf{b} \in \mathbb{R}^n$ is defined as
$$ \mathbf{a} \cdot \mathbf{b} = \sum_{k=0}^{n-1} a_k \cdot b_k $$
Your task is to implement the function dot_product(a, b) in src/assignment_01.py. Use a python for loop to iterate over the elements of the input vectors. The function should be written in a way that it can handle vectors of any length (not just the provided length of 100).
Task 2: Matrix-Matrix Multiplication
The matrix product $C = A \cdot B$ for $A \in \mathbb{R}^{m \times k}$, $B \in \mathbb{R}^{k \times n}$ and $C \in \mathbb{R}^{m \times n}$ is defined element-wise as
$$ c_{pr} = \sum_{q=0}^{k-1} a_{pq} \cdot b_{qr} $$
This corresponds to the einsum pq, qr -> pr.
Your task consists of two parts:
Implement the function
matmul_loops(A, B): Compute $C = A \cdot B$ using nestedforloops. No PyTorch matrix-multiply operations are allowed inside this function.Implement the function
matmul_dot(A, B): Compute the same product but reuse yourdot_productfunction from Task 1. To do so, use loops over thedot_productfunction that uses slices of the input matrices as 1-D views.
Task 3: Einsum acsxp, bspy -> abcxy
Given tensors
$$ A \in \mathbb{R}^{a \times c \times s \times x \times p}, \quad B \in \mathbb{R}^{b \times s \times p \times y} $$
the target einsum acsxp, bspy -> abcxy computes
$$ C_{abcxy} = \sum_{s} \sum_{p} A_{acsxp} \cdot B_{bspy} $$
You can assume a static shape for the tensors, A: (2, 4, 5, 4, 3), B: (3, 5, 3, 5) and C: (2, 3, 4, 4, 5)
Your task consists of two parts:
Implement the function
einsum_loops(A, B): Compute the einsum expression by usingforloops to iterate over all index dimensions, accumulating the products into a pre-allocated output tensor.Implement the function
einsum_gemm(A, B): Compute the same einsum but reuse one of your matrix multiplication implementations from Task 2. To do so, use loops over the matrix multiplication function that uses slices of the input tensors as 2-D views.
Optional Task: Tensor Permutation and Reshaping
Look up torch.permute and torch.reshape in the PyTorch documentation and experiment with them inside a new python file. Try to answer the following questions:
How do
.shapeand.stride()change after atorch.permuteortorch.reshapecall? Does the underlying data move in memory?How does
torch.reshapediffer fromtorch.view?Why can reshaping a permuted tensor be handled differently than reshaping a freshly created tensor? (Hint: check
.is_contiguous()before and aftertorch.permute).