<commit_before>/**
 * \file image.cu
 * \brief type declarations for GPU image buffers.
 * \copyright 2015, <NAME>, ANU. See AUTHORS for more details
 * \license 3-clause BSD, see LICENSE for more details
 */

#include <cstring>
#include <iostream>
#include <exception>

#include "flowfilter/gpu/image.h"
#include "flowfilter/gpu/gpu_deleter.h"
#include "flowfilter/gpu/error.h"

namespace flowfilter {
namespace gpu {

//#################################################
// GPUImage
//#################################################
GPUImage::GPUImage() {
    __width = 0;
    __height = 0;
    __depth = 0;
    __pitch = 0;
    __itemSize = 0;
}

GPUImage::GPUImage(const int height, const int width,
    const int depth, const int itemSize) {

    __height = height;
    __width = width;
    __depth = depth;
    __itemSize = itemSize;

    // allocate memory in GPU space
    allocate();
}

GPUImage::~GPUImage() {

    // nothing to do
    // device buffer is released by gpu_deleter
    // std::cout << "GPUImage::~GPUImage(): [" << 
    //     __height << ", " << __width << ", " << __depth << "] : " << __ptr_dev.use_count() << std::endl;
}

int GPUImage::height() const {
    return __height;
}

int GPUImage::width() const {
    return __width;
}

int GPUImage::depth() const {
    return __depth;
}

int GPUImage::pitch() const {
    return __pitch;
}

int GPUImage::itemSize() const {
    return __itemSize;
}

void* GPUImage::data() {
    return __ptr_dev.get();
}


void GPUImage::upload(flowfilter::image_t& img) {

    // check if device memory is allocated
    if(!__ptr_dev) {

        // set resolution to input image
        __width = img.width;
        __height = img.height;
        __depth = img.depth;
        __itemSize = img.itemSize;

        // allocate memory
        allocate();
    }

    // compare shapes
    if(compareShape(img)) {

        // print first 5 elements of img
        // for(int i = 0; i < 5; i ++) {
        //     std::cout << i << ": " << (int)static_cast<unsigned char*>(img.data)[i] << std::endl;
        // }

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(__ptr_dev.get(), __pitch, img.data, img.pitch,
            __width*__depth*__itemSize, __height,
            cudaMemcpyHostToDevice));

        // TODO: add support for asynchronous copy

    } else {

        std::cerr << "ERROR: GPUImage::upload(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.height << ", " << img.width << ", " << img.depth << "][" << img.itemSize << "]" << std::endl;

        return; // TODO: throw exception
    }
}

void GPUImage::download(flowfilter::image_t& img) const {

    if(!__ptr_dev) {
        std::cerr << "ERROR: GPUImage::download(): unallocated image" << std::endl;
        return; // TODO: throw exception
    }

    if(compareShape(img)) {

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(img.data, img.pitch, __ptr_dev.get(), __pitch,
            __width*__depth*__itemSize, __height, cudaMemcpyDeviceToHost));

        // print first 5 elements of img
        // for(int i = 0; i < 5; i ++) {
        //     std::cout << i << ": " << static_cast<float*>(img.data)[i] << std::endl;
        // }

    } else {
        std::cerr << "ERROR: GPUImage::download(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.height << ", " << img.width << ", " << img.depth << "][" << img.itemSize << "]" << std::endl;
        return; // TODO: throw exception
    }
}

void GPUImage::copyFrom(GPUImage& img) {

    if(compareShapeGPU(img)) {

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(__ptr_dev.get(), __pitch, 
            img.__ptr_dev.get(), img.__pitch,
            __width*__depth*__itemSize, __height, cudaMemcpyDeviceToDevice));

    } else {
        std::cerr << "ERROR: GPUImage::download(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.__height << ", " << img.__width << ", " << img.__depth << "][" << img.__itemSize << "]" << std::endl;
        throw std::exception();
    }
}

void GPUImage::clear() {

    checkError(cudaMemset2D(__ptr_dev.get(), __pitch,
        0, __width*__depth*__itemSize, __height));
}


void GPUImage::allocate() {

    // std::cout << "GPUImage::allocate()" << std::endl;

    void* buffer_dev = nullptr;
    checkError(cudaMallocPitch(&buffer_dev, &__pitch,
        __width*__depth*__itemSize, __height));

    // create a new shared pointer
    __ptr_dev = std::shared_ptr<void> {buffer_dev, gpu_deleter<void>()};
<commit_msg>Fixed message text.<commit_after>/**
 * \file image.cu
 * \brief type declarations for GPU image buffers.
 * \copyright 2015, <NAME>, ANU. See AUTHORS for more details
 * \license 3-clause BSD, see LICENSE for more details
 */

#include <cstring>
#include <iostream>
#include <exception>

#include "flowfilter/gpu/image.h"
#include "flowfilter/gpu/gpu_deleter.h"
#include "flowfilter/gpu/error.h"

namespace flowfilter {
namespace gpu {

//#################################################
// GPUImage
//#################################################
GPUImage::GPUImage() {
    __width = 0;
    __height = 0;
    __depth = 0;
    __pitch = 0;
    __itemSize = 0;
}

GPUImage::GPUImage(const int height, const int width,
    const int depth, const int itemSize) {

    __height = height;
    __width = width;
    __depth = depth;
    __itemSize = itemSize;

    // allocate memory in GPU space
    allocate();
}

GPUImage::~GPUImage() {

    // nothing to do
    // device buffer is released by gpu_deleter
    // std::cout << "GPUImage::~GPUImage(): [" << 
    //     __height << ", " << __width << ", " << __depth << "] : " << __ptr_dev.use_count() << std::endl;
}

int GPUImage::height() const {
    return __height;
}

int GPUImage::width() const {
    return __width;
}

int GPUImage::depth() const {
    return __depth;
}

int GPUImage::pitch() const {
    return __pitch;
}

int GPUImage::itemSize() const {
    return __itemSize;
}

void* GPUImage::data() {
    return __ptr_dev.get();
}


void GPUImage::upload(flowfilter::image_t& img) {

    // check if device memory is allocated
    if(!__ptr_dev) {

        // set resolution to input image
        __width = img.width;
        __height = img.height;
        __depth = img.depth;
        __itemSize = img.itemSize;

        // allocate memory
        allocate();
    }

    // compare shapes
    if(compareShape(img)) {

        // print first 5 elements of img
        // for(int i = 0; i < 5; i ++) {
        //     std::cout << i << ": " << (int)static_cast<unsigned char*>(img.data)[i] << std::endl;
        // }

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(__ptr_dev.get(), __pitch, img.data, img.pitch,
            __width*__depth*__itemSize, __height,
            cudaMemcpyHostToDevice));

        // TODO: add support for asynchronous copy

    } else {

        std::cerr << "ERROR: GPUImage::upload(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.height << ", " << img.width << ", " << img.depth << "][" << img.itemSize << "]" << std::endl;

        return; // TODO: throw exception
    }
}

void GPUImage::download(flowfilter::image_t& img) const {

    if(!__ptr_dev) {
        std::cerr << "ERROR: GPUImage::download(): unallocated image" << std::endl;
        return; // TODO: throw exception
    }

    if(compareShape(img)) {

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(img.data, img.pitch, __ptr_dev.get(), __pitch,
            __width*__depth*__itemSize, __height, cudaMemcpyDeviceToHost));

        // print first 5 elements of img
        // for(int i = 0; i < 5; i ++) {
        //     std::cout << i << ": " << static_cast<float*>(img.data)[i] << std::endl;
        // }

    } else {
        std::cerr << "ERROR: GPUImage::download(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.height << ", " << img.width << ", " << img.depth << "][" << img.itemSize << "]" << std::endl;
        return; // TODO: throw exception
    }
}

void GPUImage::copyFrom(GPUImage& img) {

    if(compareShapeGPU(img)) {

        // issue synchronous memory copy
        checkError(cudaMemcpy2D(__ptr_dev.get(), __pitch, 
            img.__ptr_dev.get(), img.__pitch,
            __width*__depth*__itemSize, __height, cudaMemcpyDeviceToDevice));

    } else {
        std::cerr << "ERROR: GPUImage::copyFrom(): shapes do not match."
            << "required: [" << __height << ", " << __width << ", " << __depth << "][" << __itemSize << "], passed: "
            << "[" << img.__height << ", " << img.__width << ", " << img.__depth << "][" << img.__itemSize << "]" << std::endl;
        throw std::exception();
    }
}

void GPUImage::clear() {

    checkError(cudaMemset2D(__ptr_dev.get(), __pitch,
        0, __width*__depth*__itemSize, __height));
}


void GPUImage::allocate() {

    // std::cout << "GPUImage::allocate()" << std::endl;

    void* buffer_dev = nullptr;
    checkError(cudaMallocPitch(&buffer_dev, &__pitch,
        __width*__depth*__itemSize, __height));

    // create a new shared pointer
    __ptr_dev = std::shared_ptr<void> {buffer_dev, gpu_deleter<void>()};

{'fraction_non_alphanumeric': 0.19003918333677047, 'fraction_numerical': 0.004330789853578057, 'mean_word_length': 2.6710825132475398, 'pattern_counts': {'":': 4, '<': 347, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '717421', 'n_tokens_mistral': 3158, 'n_tokens_neox': 3021, 'n_words': 688}