Skip to content
Extraits de code Groupes Projets
main.cpp 8,75 ko
Newer Older
  • Learn to ignore specific revisions
  • JordanHanotiaux's avatar
    JordanHanotiaux a validé
    #include "matrix_opencl.hpp"
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    // Remplace ceci par un header propre si possible
    // #include "mlp_sgd.cpp"  <-- Éviter cela
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    #include <iostream>
    #include <vector>
    #include <cassert>
    #include <stdexcept>
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    #include <cmath>
    #include <limits>
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    #include <chrono>
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    // Helper function to print a matrix (copies to host first)
    void printMatrix(const std::string& label, const MatrixCL& mat) {
        std::cout << label << " (" << mat.numRows() << "x" << mat.numCols() << "):\n";
        try {
            std::vector<float> host_data = mat.copyToHost();
            for (int i = 0; i < mat.numRows(); ++i) {
                std::cout << "  [";
                for (int j = 0; j < mat.numCols(); ++j) {
                    std::cout << " " << host_data[i * mat.numCols() + j];
                }
                std::cout << " ]\n";
            }
             std::cout << std::endl;
        } catch (const std::runtime_error& e) {
            std::cerr << "Error printing matrix: " << e.what() << std::endl;
        }
    }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    // Helper function for approximate float comparison
    bool approxEqual(float a, float b, float epsilon = 1e-5f) {
        return std::abs(a - b) < epsilon;
    }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    // Helper function to verify matrix contents
    bool verifyMatrix(const std::string& label, const MatrixCL& mat, const std::vector<float>& expected, float epsilon = 1e-5f) {
        std::cout << "Verifying " << label << "..." << std::endl;
        if (static_cast<size_t>(mat.numRows() * mat.numCols()) != expected.size()) {
            std::cerr << "Verification failed: Dimension mismatch for " << label << ". Got "
                      << mat.numRows() << "x" << mat.numCols() << ", expected " << expected.size() << " elements." << std::endl;
            return false;
        }
        try {
            std::vector<float> actual = mat.copyToHost();
            bool match = true;
            for (size_t i = 0; i < actual.size(); ++i) {
                if (!approxEqual(actual[i], expected[i], epsilon)) {
                    std::cerr << "Verification failed for " << label << " at index " << i
                              << ". Got " << actual[i] << ", expected " << expected[i] << std::endl;
                    match = false;
                    // Don't break, report all mismatches if desired, or break here for efficiency
                     break;
                }
            }
            if (match) {
                std::cout << label << " verified successfully." << std::endl;
            } else {
                 std::cout << label << " verification failed." << std::endl;
            }
            return match;
        } catch (const std::runtime_error& e) {
            std::cerr << "Error verifying matrix " << label << ": " << e.what() << std::endl;
            return false;
        }
    }
    
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    cl_ulong getElapsedTime(const cl::Event& event) {
        cl_ulong start = event.getProfilingInfo<CL_PROFILING_COMMAND_START>();
        cl_ulong end = event.getProfilingInfo<CL_PROFILING_COMMAND_END>();
        return end - start; // In nanoseconds
    }
    
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    int main() {
        try {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            // --- OpenCL Setup ---
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::cout << "--- OpenCL Setup ---" << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::vector<cl::Platform> platforms;
            cl::Platform::get(&platforms);
            if (platforms.empty()) {
                std::cerr << "No OpenCL platforms found." << std::endl;
                return 1;
            }
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            cl::Platform platform = platforms.front();
            std::cout << "Using Platform: " << platform.getInfo<CL_PLATFORM_NAME>() << std::endl;
    
            std::vector<cl::Device> devices;
            platform.getDevices(CL_DEVICE_TYPE_GPU, &devices);
            if (devices.empty()) {
                std::cout << "No GPU found, trying CPU..." << std::endl;
                platform.getDevices(CL_DEVICE_TYPE_CPU, &devices);
                if (devices.empty()) {
                    std::cerr << "No OpenCL devices found." << std::endl;
                    return 1;
                }
            }
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            cl::Device device = devices.front();
            std::cout << "Using Device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            cl::Context context(device);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            cl_int err;
            cl_command_queue q = clCreateCommandQueue(context(), device(), CL_QUEUE_PROFILING_ENABLE, &err);
            if (err != CL_SUCCESS) {
                std::cerr << "clCreateCommandQueue failed: " << err << std::endl;
                exit(1);
            }
            cl::CommandQueue queue(q);
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::vector<cl::Device> devices_to_init = { device };
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            try {
                MatrixCL::initializeKernels(context, devices_to_init);
                std::cout << "Kernel initialization successful." << std::endl;
            } catch (const std::exception& e) {
                std::cerr << "FATAL ERROR during kernel initialization: " << e.what() << std::endl;
                return 1;
            }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            // --- Matrix Multiplication Benchmark ---
            std::cout << "\n--- Matrix Multiplication Benchmark (growing sizes) ---" << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::vector<int> sizes = {5000};
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            for (int size : sizes) {
                std::cout << "\nMultiplying " << size << "x" << size << " matrices..." << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                std::vector<float> dataA(size * size, 1.0f); // Matrix A filled with ones
                std::vector<float> dataB(size * size, 2.0f); // Matrix B filled with twos
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                MatrixCL matA(size, size, context, queue, &dataA);
                MatrixCL matB(size, size, context, queue, &dataB);
                MatrixCL result(size, size, context, queue); // Output matrix
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                auto start = std::chrono::high_resolution_clock::now();
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                result = matA * matB; // Matrix multiplication
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                queue.finish(); // S'assurer que le kernel est bien terminé
    
                auto end = std::chrono::high_resolution_clock::now();
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                auto elapsed_us = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                std::cout << elapsed_us << " s " << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            }
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            // 2. --- Basic Matrix Operations Test ---
            std::cout << "\n--- Basic Matrix Operations Test ---" << std::endl;
    
            std::vector<float> dataA = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}; // 2x3
            std::vector<float> dataB = {7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f}; // 2x3
            std::vector<float> dataC = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f}; // 3x3
    
            MatrixCL matA(2, 3, context, queue, &dataA);
            MatrixCL matB(2, 3, context, queue, &dataB);
            MatrixCL matC(3, 3, context, queue, &dataC);
            MatrixCL matD(2, 3, context, queue); // Initialized to 0 by constructor
    
            printMatrix("Matrix A (original)", matA);
            printMatrix("Matrix B", matB);
            printMatrix("Matrix C (3x3)", matC);
            printMatrix("Matrix D (initially zero)", matD);
    
            // Test fill
            matD.fill(5.5f);
            printMatrix("Matrix D after fill(5.5)", matD);
            assert(verifyMatrix("Matrix D fill", matD, {5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f}));
    
            // Test Copy Constructor
            MatrixCL matA_copy(matA);
            printMatrix("Matrix A Copy (via copy constructor)", matA_copy);
            assert(verifyMatrix("Matrix A Copy Ctor", matA_copy, dataA));
    
            // Test Copy Assignment Operator
            MatrixCL matD_assigned(1, 1, context, queue); // Create with different dimensions
            matD_assigned = matD;
            printMatrix("Matrix D Assigned (via assignment operator)", matD_assigned);
            assert(verifyMatrix("Matrix D Assignment Op", matD_assigned, {5.5f, 5.5f, 5.5f, 5.5f, 5.5f, 5.5f}));
    
    
            // Test Addition
            MatrixCL matAdd = matA + matB;
            printMatrix("Matrix A + B", matAdd);
            assert(verifyMatrix("Matrix A + B", matAdd, {8.0f, 10.0f, 12.0f, 14.0f, 16.0f, 18.0f}));
    
            // Test Transpose
            MatrixCL matATrans = matA.transpose();
            printMatrix("Matrix A Transposed", matATrans); // Should be 3x2
            assert(verifyMatrix("Matrix A Transposed", matATrans, {1.0f, 4.0f, 2.0f, 5.0f, 3.0f, 6.0f}));
    
            // Test Matrix Multiplication: A(2x3) * C(3x3) -> Result(2x3)
            // Expected: [ (1*1+2*4+3*7) (1*2+2*5+3*8) (1*3+2*6+3*9) ] = [ 30 36 42 ]
            //           [ (4*1+5*4+6*7) (4*2+5*5+6*8) (4*3+5*6+6*9) ] = [ 66 81 96 ]
            MatrixCL matMul = matA * matC;
            printMatrix("Matrix A * C", matMul);
            assert(verifyMatrix("Matrix A * C", matMul, {30.0f, 36.0f, 42.0f, 66.0f, 81.0f, 96.0f}));
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        } catch (const cl::BuildError& err) {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::cerr << "OpenCL Build Error: " << err.what() << " (" << err.err() << ")" << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            for (const auto& pair : err.getBuildLog()) {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
                std::cerr << "Device " << pair.first.getInfo<CL_DEVICE_NAME>() << " Build Log:\n"
                          << pair.second << std::endl;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            }
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            return 1;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
        } catch (const cl::Error& err) {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::cerr << "OpenCL Error: " << err.what() << " (" << err.err() << ")" << std::endl;
            return 1;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
        } catch (const std::exception& e) {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            std::cerr << "Standard Exception: " << e.what() << std::endl;
            return 1;
        }
    
        std::cout << "\nAll OpenCL Matrix and MLP tests completed successfully." << std::endl;
        return 0;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    }