ddemidov / vexcl

VexCL is a C++ vector expression template library for OpenCL/CUDA/OpenMP
http://vexcl.readthedocs.org
MIT License
701 stars 81 forks source link

Support of std::complex #208

Closed eti-p-doray closed 8 years ago

eti-p-doray commented 8 years ago

It seems like vexcl does not support std::complex since a specialization for type_name is not provided. I initially used cl_float2 as a replacement, but doing so either pollutes host vectors with cl types or requires a non-trivial conversion. Since the standard requires std::complex to have the same memory layout as a c-style array, I would guess support for complex in vexcl is as trivial as specializing type_name_impl :

template<class T>
struct vex::type_name_impl<std::complex<T>> {
  static std::string get() { return vex::type_name<T>() + "2"; }
};

I am new to vexcl and I'd like feedback on this idea.

ddemidov commented 8 years ago

OpenCL does not support complex type natively, so its not possible to map e.g. std::complex<double> to cl_double2 directly. The workaround you proposed will work as long as you don't use complex multiplication or division (cl_* types do those operations elementwise).

If you are targeting AMD OpenCL 1.2 or above, or when OpenCL 2.2 is widely available, its possible to use C++ language in compute kernels and functions. This means that you can introduce a new complex type that is binary compatible with std::complex and overload arithmetic operations for the type. In fact, I've just tried it for amgcl, and it works perfectly:

https://github.com/ddemidov/amgcl/blob/vexcl-non-scalar/amgcl/backend/vexcl_complex.hpp

The function amgcl::backend::enable_complex_for_vexcl adds necessary program header and OpenCL compile options to all subsequently generated kernels, so that you can use std::complex natively in vexcl expressions (both for OpenCL and CUDA backends).

In principle, this function could be migrated into core vexcl. Would that be of use for you?

eti-p-doray commented 8 years ago

Thanks for your answer! Having complex types defined in kernels is a cool feature. Unfortunately, I do not have access to a C++ compatible gpu (and I don't think OpenCL 2.2 drivers are widely available yet). In my case, I use FFT with cl_float2 and the workaround allows me to seamlessly provide the function with complex types. I initially though that VexCl could specialize type_name() the same way as above, but this could lead to confusion as cl_float2 does not behave like a complex type in kernels.

ddemidov commented 8 years ago

Can this be closed, or do you feel it is possible to somehow improve the complex values interface?