Shared Code

by asfasfasfsafasfasfasf65·16 views·May 7, 2026Open in Playground →
main.cu
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <vector>
#include <cmath>

#define BORDE_SUPERIOR 100.0f
#define BORDES 0.0f

#define BLOCK_W 16
#define BLOCK_H 16
#define INNER_W 14
#define INNER_H 14

int MatrixSide = 1024;
int N_Steps = 5;

// ------------------- Kernel original -------------------
__global__ void UpdateMatrixOriginal(const int n, float* input, float* buffer)
{
    int tx = threadIdx.x;
    int ty = threadIdx.y;
    int idx_col = blockIdx.x * blockDim.x + tx;
    int idx_row = blockIdx.y * blockDim.y + ty;

    __shared__ float shMemHalo[BLOCK_H + 2][BLOCK_W + 2];

    int sharedX = tx + 1;
    int sharedY = ty + 1;

    float value = 0.0f;
    if (idx_col < n && idx_row < n)
        value = input[idx_row * n + idx_col];
    shMemHalo[sharedY][sharedX] = value;

    // Halos
    if (tx == 0)
        shMemHalo[sharedY][0] = (idx_col > 0) ? input[idx_row * n + idx_col - 1] : BORDES;
    if (tx == blockDim.x - 1 || idx_col == n - 1)
        shMemHalo[sharedY][sharedX + 1] = (idx_col < n - 1) ? input[idx_row * n + idx_col + 1] : BORDES;
    if (ty == 0)
        shMemHalo[0][sharedX] = (idx_row > 0) ? input[(idx_row - 1) * n + idx_col] : BORDE_SUPERIOR;
    if (ty == blockDim.y - 1 || idx_row == n - 1)
        shMemHalo[sharedY + 1][sharedX] = (idx_row < n - 1) ? input[(idx_row + 1) * n + idx_col] : BORDES;

    __syncthreads();

    if (idx_col > 0 && idx_col < n - 1 && idx_row > 0 && idx_row < n - 1)
    {
        buffer[idx_row * n + idx_col] = 0.25f * (
            shMemHalo[sharedY - 1][sharedX] +
            shMemHalo[sharedY + 1][sharedX] +
            shMemHalo[sharedY][sharedX - 1] +
            shMemHalo[sharedY][sharedX + 1]
        );
    }
}

// ------------------- Kernel optimizado 14x14 (usando 16x16 tile con halo) -------------------
__global__ void UpdateMatrixTile14x14(const int n, float* input, float* buffer)
{
    __shared__ float tile[BLOCK_H + 2][BLOCK_W + 2];

    int tx = threadIdx.x;
    int ty = threadIdx.y;

    int global_x = blockIdx.x * INNER_W + tx - 1;
    int global_y = blockIdx.y * INNER_H + ty - 1;

    // Cargar valor dentro de tile (con halo)
    float value = 0.0f;
    if (global_x >= 0 && global_x < n && global_y >= 0 && global_y < n)
        value = input[global_y * n + global_x];

    tile[ty][tx] = value;

    __syncthreads();

    // Región interna del bloque (14x14)
    if (tx >= 1 && tx <= INNER_W && ty >= 1 && ty <= INNER_H &&
        global_x > 0 && global_x < n - 1 && global_y > 0 && global_y < n - 1)
    {
        buffer[global_y * n + global_x] = 0.25f * (
            tile[ty - 1][tx] +
            tile[ty + 1][tx] +
            tile[ty][tx - 1] +
            tile[ty][tx + 1]
        );
    }
}

// ------------------- Checksum -------------------
float checksum(const std::vector<float>& mat)
{
    double sum = 0.0;
    for (float v : mat)
        sum += v;
    return static_cast<float>(sum);
}

// ------------------- Main -------------------
int main()
{
    size_t bytes = MatrixSide * MatrixSide * sizeof(float);
    std::vector<float> h_matrix(MatrixSide * MatrixSide, 0.0f);

    // Borde superior
    for (int col = 0; col < MatrixSide; col++)
        h_matrix[col] = BORDE_SUPERIOR;

    float* d_in;
    float* d_out;
    cudaMalloc(&d_in, bytes);
    cudaMalloc(&d_out, bytes);
    cudaMemcpy(d_in, h_matrix.data(), bytes, cudaMemcpyHostToDevice);

    dim3 dimBlock(BLOCK_W, BLOCK_H);
    dim3 dimGrid((MatrixSide + INNER_W - 1) / INNER_W, (MatrixSide + INNER_H - 1) / INNER_H);

    // Warmup
    UpdateMatrixOriginal<<<dimGrid, dimBlock>>>(MatrixSide, d_in, d_out);
    cudaDeviceSynchronize();
    UpdateMatrixTile14x14<<<dimGrid, dimBlock>>>(MatrixSide, d_in, d_out);
    cudaDeviceSynchronize();

    // --- Kernel original ---
    cudaMemcpy(d_in, h_matrix.data(), bytes, cudaMemcpyHostToDevice);
    cudaEvent_t start1, stop1;
    cudaEventCreate(&start1);
    cudaEventCreate(&stop1);
    cudaEventRecord(start1);
    for (int step = 0; step < N_Steps; step++)
    {
        UpdateMatrixOriginal<<<dimGrid, dimBlock>>>(MatrixSide, d_in, d_out);
        cudaDeviceSynchronize();
        std::swap(d_in, d_out);
    }
    cudaEventRecord(stop1);
    cudaEventSynchronize(stop1);
    float timeOriginal = 0;
    cudaEventElapsedTime(&timeOriginal, start1, stop1);
    std::cout << "Tiempo kernel original: " << timeOriginal << " ms\n";

    std::vector<float> h_result_original(MatrixSide * MatrixSide);
    cudaMemcpy(h_result_original.data(), d_in, bytes, cudaMemcpyDeviceToHost);
    float checksum_original = checksum(h_result_original);
    std::cout << "Checksum kernel original: " << checksum_original << "\n";

    // --- Kernel optimizado ---
    cudaMemcpy(d_in, h_matrix.data(), bytes, cudaMemcpyHostToDevice);
    cudaEvent_t start2, stop2;
    cudaEventCreate(&start2);
    cudaEventCreate(&stop2);
    cudaEventRecord(start2);
    for (int step = 0; step < N_Steps; step++)
    {
        UpdateMatrixTile14x14<<<dimGrid, dimBlock>>>(MatrixSide, d_in, d_out);
        cudaDeviceSynchronize();
        std::swap(d_in, d_out);
    }
    cudaEventRecord(stop2);
    cudaEventSynchronize(stop2);
    float timeTile = 0;
    cudaEventElapsedTime(&timeTile, start2, stop2);
    std::cout << "Tiempo kernel optimizado (14x14): " << timeTile << " ms\n";

    std::vector<float> h_result_tile(MatrixSide * MatrixSide);
    cudaMemcpy(h_result_tile.data(), d_in, bytes, cudaMemcpyDeviceToHost);
    float checksum_tile = checksum(h_result_tile);
    std::cout << "Checksum kernel optimizado: " << checksum_tile << "\n";

    // --- Comparación ---
    float epsilon = 1e-4f;
    if (std::fabs(checksum_original - checksum_tile) < epsilon)
        std::cout << "✅ Los resultados coinciden!\n";
    else
        std::cout << "❌ Diferencia en resultados!\n";

    cudaFree(d_in);
    cudaFree(d_out);
    return 0;
}

Comments (0)

to post comments and vote
No comments yet. Be the first to share your thoughts!