Skip to content

cselab/cuda_variant

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Variant

Boost provides boost::variant to provide a type-checked discriminated union type.

This library provides a simple variant type similar in concept to boost::variant, that works in CUDA, for use in GPU code as well as CPU code.

This type is not as fully featured as boost::variant: it does not support recursive variants, nor does it support variants of references. However, it does support variants of non-POD data types, unlike C++03 unions.

variants are accessed by means of functor classes that overload operator() for all types in the variant, and then are applied using apply_visitor(), as shown in the example. Compile-time errors result from trying to visit variants with functors that do not provide overloads for all types in the variant. This is an important safety benefit.

To extract a known type T from a variant, use variant::get<T>. On the CPU, this will throw a std::runtime_exception if the variant currently contains a type other than T.

On the GPU, if get<T> fails at runtime, the program will be terminated - it is treated as a catastrophic error.

This code has been tested on Linux, which NVCC 7.0 and g++ 4.8.

Usage

#include <variant/variant.h>
#include <iostream>
#include <thrust/copy.h>
#include <thrust/device_vector.h>

//Non-pod type
struct foo{
    int o;
    __host__ __device__
    foo(int _o) : o(_o) {};
};

//Declare a variant type
typedef variant::variant<int, foo> my_variant;

//Accessing a variant type is done through a visitor functor.
//This provides type safety: at compile time you will get an
//error if you try to access a variant type by a functor.
//that does not know how to operate on all types which the
//variant may contain.
struct my_visitor {
    __host__ __device__
    int operator()(const int& i) const {
        return i + 10;
    }
    __host__ __device__
    int operator()(const foo& i) const {
        return i.o + 20;
    }
};


//A functor that applies the visitor
//This is just a convenience when using Thrust
struct extractor {
    typedef int result_type;
    __host__ __device__
    int operator()(const my_variant& v) const {
        //The actual access to the variant is done by
        //calling apply_visitor, with two arguments:
        //1. The static_visitor which operates on the variant
        //2. The variant being accessed
        return variant::apply_visitor(my_visitor(), v);
    }
};



int main() {
    
    //Make a vector of variants on the GPU
    thrust::device_vector<my_variant> x(2);

    //Initialize their elements
    x[0] = 1;
    x[1] = foo(2);
    thrust::device_vector<int> y(2);

    //Visit the vector on the GPU
    thrust::transform(x.begin(), x.end(), y.begin(), extractor());
    std::ostream_iterator<int> os(std::cout, " ");
    std::cout << "GPU result : ";
    thrust::copy(y.begin(), y.end(), os);
    std::cout << std::endl;
   
    
    thrust::host_vector<my_variant> h_x = x;
    thrust::host_vector<int> h_y(2);

    //Visit the vector on the CPU
    thrust::transform(h_x.begin(), h_x.end(), h_y.begin(), extractor());
    std::cout << "CPU result : ";
    thrust::copy(h_y.begin(), h_y.end(), os);
    std::cout << std::endl;

    std::cout << "Truth      : 11 22" << std::endl;
    
}

Releases

No releases published

Packages

No packages published

Languages

  • C++ 69.6%
  • Cuda 27.9%
  • Makefile 2.5%
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy