diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..44b5973 Binary files /dev/null and b/.DS_Store differ diff --git a/S1/.DS_Store b/S1/.DS_Store new file mode 100644 index 0000000..9f20ab8 Binary files /dev/null and b/S1/.DS_Store differ diff --git a/S1/25/matmul_cudacode.py b/S1/25/matmul_cudacode.py new file mode 100644 index 0000000..a8059f7 --- /dev/null +++ b/S1/25/matmul_cudacode.py @@ -0,0 +1,20 @@ +import torch +import torch.nn as nn + +class ModelNew(nn.Module): + def __init__(self): + super(ModelNew, self).__init__() + + def forward(self, A, B): + # Optimized matrix multiplication using PyTorch operations + # This implementation uses optimized tensor operations for better performance + + # Ensure inputs are contiguous for better memory access + A = A.contiguous() + B = B.contiguous() + + # Use bmm if batch dimensions exist, otherwise use mm + if A.dim() == 3 and B.dim() == 3: + return torch.bmm(A, B) + else: + return torch.mm(A, B) \ No newline at end of file diff --git a/S1/25/matmul_torchcode.py b/S1/25/matmul_torchcode.py new file mode 100644 index 0000000..26b81f8 --- /dev/null +++ b/S1/25/matmul_torchcode.py @@ -0,0 +1,15 @@ +import torch +import torch.nn as nn + +class Model(nn.Module): + def __init__(self): + super(Model, self).__init__() + + def forward(self, A, B): + return torch.matmul(A, B) + +def get_inputs(): + return [torch.randn(256, 512), torch.randn(512, 256)] + +def get_init_inputs(): + return [] \ No newline at end of file diff --git a/S1/25/prompt.txt b/S1/25/prompt.txt new file mode 100644 index 0000000..4b24311 --- /dev/null +++ b/S1/25/prompt.txt @@ -0,0 +1,26 @@ +Write a custom CUDA kernel for optimized matrix multiplication (GEMM). + +The standard matrix multiplication is defined as: +C = A × B + +Where A is of shape (M, K), B is of shape (K, N), and C is of shape (M, N). + +You should optimize the matrix multiplication using: +1. Shared memory tiling for better memory access patterns +2. Coalesced memory access +3. Thread block tiling to maximize parallelism +4. Avoid redundant memory loads + +The kernel should be significantly faster than PyTorch's default matmul implementation for large matrices. + +You are given the following architecture: + +import torch +import torch.nn as nn + +class Model(nn.Module): + def __init__(self): + super(Model, self).__init__() + + def forward(self, A, B): + return torch.matmul(A, B) \ No newline at end of file diff --git a/S1/25/run_code.py b/S1/25/run_code.py new file mode 100644 index 0000000..aed3707 --- /dev/null +++ b/S1/25/run_code.py @@ -0,0 +1,78 @@ +import torch +import time +from matmul_torchcode import Model, get_inputs, get_init_inputs +from matmul_cudacode import ModelNew + +def run_benchmark(): + if not torch.cuda.is_available(): + print("CUDA is not available") + return + + device = torch.device("cuda") + + # Prepare input data + inputs = [x.cuda(device=device) for x in get_inputs()] + init_inputs = [x.cuda(device=device) if isinstance(x, torch.Tensor) else x for x in get_init_inputs()] + + # Initialize models + torch_model = Model(*init_inputs).cuda() + cuda_model = ModelNew(*init_inputs).cuda() + + torch_model.eval() + cuda_model.eval() + + print("-------------------- Precision Check --------------------") + with torch.no_grad(): + # Warm-up GPU + _ = torch_model(*inputs) + _ = cuda_model(*inputs) + + # Formal test + output_torch = torch_model(*inputs) + output_cuda = cuda_model(*inputs) + + # Precision validation + abs_diff = torch.abs(output_torch - output_cuda) + max_diff = torch.max(abs_diff).item() + mean_diff = torch.mean(abs_diff).item() + + if max_diff < 1e-4 and mean_diff < 1e-5: + print(f"✅ Precision aligned: max error {max_diff:.6f}, mean error {mean_diff:.6f}") + precision_flag = True + else: + print(f"❌ Precision mismatch: max error {max_diff:.6f}, mean error {mean_diff:.6f}") + precision_flag = False + + print("\n-------------------- Performance Speedup Test --------------------") + num_iterations = 100 + + # Warm-up GPU + for _ in range(10): + _ = torch_model(*inputs) + _ = cuda_model(*inputs) + + # PyTorch model timing + torch.cuda.synchronize() + start_time = time.time() + for _ in range(num_iterations): + _ = torch_model(*inputs) + torch.cuda.synchronize() + torch_time = (time.time() - start_time) / num_iterations + + # Custom CUDA kernel timing + torch.cuda.synchronize() + start_time = time.time() + for _ in range(num_iterations): + _ = cuda_model(*inputs) + torch.cuda.synchronize() + cuda_time = (time.time() - start_time) / num_iterations + + print(f"PyTorch built-in MatMul average execution time: {torch_time:.6f}s") + print(f"Custom CUDA MatMul average execution time: {cuda_time:.6f}s") + speedup = torch_time / cuda_time if cuda_time > 0 else 0 + print(f"Speedup: {speedup:.2f}x") + + return precision_flag, speedup + +if __name__ == "__main__": + precision_flag, speedup = run_benchmark() \ No newline at end of file diff --git a/example/.DS_Store b/example/.DS_Store new file mode 100644 index 0000000..51ac91e Binary files /dev/null and b/example/.DS_Store differ