Skip to content

Commit

Permalink
Merge pull request #2364 from khalednasr/feature/linalg
Browse files Browse the repository at this point in the history
Implemented a class for GPU vectors
  • Loading branch information
lambday committed Jul 5, 2014
2 parents 9d21aef + c44b8c9 commit db545fd
Show file tree
Hide file tree
Showing 10 changed files with 649 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/shogun/lib/GPUMatrix.cpp
Expand Up @@ -70,7 +70,7 @@ CGPUMatrix<T>::CGPUMatrix(VCLMemoryArray mem, index_t nrows, index_t ncols,
}

template <class T>
CGPUMatrix<T>::CGPUMatrix(SGMatrix< T >& cpu_mat)
CGPUMatrix<T>::CGPUMatrix(const SGMatrix< T >& cpu_mat)
{
init();

Expand Down
16 changes: 13 additions & 3 deletions src/shogun/lib/GPUMatrix.h
Expand Up @@ -55,7 +55,7 @@ namespace shogun
* as backend for managing GPU memory.
*
* It supports conversion to/from SGMatrix objects and Eigen3 matrices. Native
* ViennaCL methods can also be using on this class through vcl_matrix()
* ViennaCL methods can also be used on the data of the matrix through vcl_matrix()
*
* Supported scalar types: char, uint8_t, int16_t, uint16_t, int32_t,
* uint32_t, int64_t, uint64_t, float32_t, float64_t.
Expand Down Expand Up @@ -87,12 +87,12 @@ template <class T> class CGPUMatrix
CGPUMatrix(VCLMemoryArray mem, index_t nrows, index_t ncols, index_t mem_offset=0);

/** Creates a gpu matrix using data from an SGMatrix */
CGPUMatrix(SGMatrix<T>& cpu_mat);
CGPUMatrix(const SGMatrix<T>& cpu_mat);

#ifdef HAVE_EIGEN3
/** Creates a gpu matrix using data from an Eigen3 matrix */
template <class Derived>
CGPUMatrix(Eigen::PlainObjectBase<Derived>& cpu_mat)
CGPUMatrix(const Eigen::PlainObjectBase<Derived>& cpu_mat)
{
init();

Expand Down Expand Up @@ -126,6 +126,16 @@ template <class T> class CGPUMatrix
vcl_matrix().clear();
}

/** Sets all the elements of the matrix to a constant value
*
* @param value New value for all the elements in the matrix
*/
void set_const(T value)
{
VCLMatrixBase m = vcl_matrix();
viennacl::linalg::matrix_assign(m, value);
}

/** Displays the matrix */
void display_matrix(const char* name="matrix") const
{
Expand Down
137 changes: 137 additions & 0 deletions src/shogun/lib/GPUVector.cpp
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2014, Shogun Toolbox Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Written (W) 2014 Khaled Nasr
*/

#include <shogun/lib/config.h>

#ifdef HAVE_VIENNACL

#include <shogun/lib/GPUVector.h>

namespace shogun
{

template <class T>
CGPUVector<T>::CGPUVector()
{
init();
}

template <class T>
CGPUVector<T>::CGPUVector(index_t length)
{
init();

vlen = length;

viennacl::backend::memory_create(vector, sizeof(T)*vlen,
viennacl::context());
}

template <class T>
CGPUVector<T>::CGPUVector(VCLMemoryArray mem, index_t length, index_t mem_offset)
{
init();

vector = mem;
vlen = length;
offset = mem_offset;
}

template <class T>
CGPUVector<T>::CGPUVector(const SGVector<T>& cpu_vec)
{
init();
vlen = cpu_vec.vlen;

viennacl::backend::memory_create(vector, sizeof(T)*vlen,
viennacl::context());

viennacl::backend::memory_write(vector, 0, vlen*sizeof(T),
cpu_vec.vector);
}

#ifdef HAVE_EIGEN3
template <class T>
CGPUVector<T>::operator Eigen::Matrix<T, Eigen::Dynamic, 1>() const
{
Eigen::Matrix<T, Eigen::Dynamic, 1> cpu_vec(vlen);

viennacl::backend::memory_read(vector, offset*sizeof(T), vlen*sizeof(T),
cpu_vec.data());

return cpu_vec;
}

template <class T>
CGPUVector<T>::operator Eigen::Matrix<T, 1, Eigen::Dynamic>() const
{
Eigen::Matrix<T, 1, Eigen::Dynamic> cpu_vec(vlen);

viennacl::backend::memory_read(vector, offset*sizeof(T), vlen*sizeof(T),
cpu_vec.data());

return cpu_vec;
}
#endif

template <class T>
CGPUVector<T>::operator SGVector<T>() const
{
SGVector<T> cpu_vec(vlen);

viennacl::backend::memory_read(vector, offset*sizeof(T), vlen*sizeof(T),
cpu_vec.vector);

return cpu_vec;
}

template <class T>
void CGPUVector<T>::init()
{
vlen = 0;
offset = 0;
}

template class CGPUVector<char>;
template class CGPUVector<uint8_t>;
template class CGPUVector<int16_t>;
template class CGPUVector<uint16_t>;
template class CGPUVector<int32_t>;
template class CGPUVector<uint32_t>;
template class CGPUVector<int64_t>;
template class CGPUVector<uint64_t>;
template class CGPUVector<float32_t>;
template class CGPUVector<float64_t>;
}

#endif
184 changes: 184 additions & 0 deletions src/shogun/lib/GPUVector.h
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2014, Shogun Toolbox Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Written (W) 2014 Khaled Nasr
*/

#ifndef __GPUVECTOR_H__
#define __GPUVECTOR_H__

#include <shogun/lib/config.h>

#ifdef HAVE_VIENNACL

#include <shogun/lib/SGVector.h>

#include <viennacl/vector.hpp>

#ifdef HAVE_EIGEN3
#include <shogun/mathematics/eigen3.h>
#endif

namespace shogun
{

/** @brief Represents a vector on the GPU
*
* This class handles vectors on the GPU using [ViennaCL](http://viennacl.sourceforge.net/)
* as backend for managing GPU memory.
*
* It supports conversion to/from SGVector objects and Eigen3 vectors. Native
* ViennaCL methods can also be used on the vector's data through vcl_vector()
*
* Supported scalar types: char, uint8_t, int16_t, uint16_t, int32_t,
* uint32_t, int64_t, uint64_t, float32_t, float64_t.
*/
template <class T> class CGPUVector
{
typedef viennacl::vector_base<T> VCLVectorBase;
typedef viennacl::backend::mem_handle VCLMemoryArray;

public:
/** Default Constructor */
CGPUVector();

/** Creates a new vector
*
* @param length Number of elements
*/
CGPUVector(index_t length);

/** Wraps a vector around an existing memery segment
*
* @param mem A memory segment
* @param length Number of elements
* @param mem_offset Offset for the memory segment, i.e the data of the vector
* starts at mem+mem_offset
*/
CGPUVector(VCLMemoryArray mem, index_t length, index_t mem_offset=0);

/** Creates a gpu vector using data from an SGVector */
CGPUVector(const SGVector<T>& cpu_vec);

#ifdef HAVE_EIGEN3
/** Creates a gpu vector using data from an Eigen3 vector */
template <class Derived>
CGPUVector(const Eigen::PlainObjectBase<Derived>& cpu_vec)
{
init();
vlen = cpu_vec.size();

viennacl::backend::memory_create(vector, sizeof(T)*vlen,
viennacl::context());

viennacl::backend::memory_write(vector, 0, vlen*sizeof(T),
cpu_vec.data());
}

/** Converts the vector into an Eigen3 column vector */
operator Eigen::Matrix<T, Eigen::Dynamic, 1>() const;

/** Converts the vector into an Eigen3 row vector */
operator Eigen::Matrix<T, 1, Eigen::Dynamic>() const;
#endif

/** Converts the vector into an SGVector */
operator SGVector<T>() const;

/** Returns a ViennaCL vector wrapped around the data of this vector. Can be
* used to call native ViennaCL methods on this vector
*/
VCLVectorBase vcl_vector()
{
return VCLVectorBase(vector,vlen, offset, 1);
}

/** Sets all the elements of the vector to zero */
void zero()
{
vcl_vector().clear();
}

/** Sets all the elements of the vector to a constant value
*
* @param value New value for all the elements in the vector
*/
void set_const(T value)
{
VCLVectorBase v = vcl_vector();
viennacl::linalg::vector_assign(v, value);
}

/** Displays the vector */
void display_vector(const char* name="vector") const
{
((SGVector<T>)*this).display_vector(name);
}

/** Read only memory access. Note that this is very slow as it copies the
* element from the GPU to the CPU
*
* @param index Element index
*/
inline viennacl::const_entry_proxy<T> operator[](index_t index) const
{
return viennacl::const_entry_proxy<T>(offset+index, vector);
}

/** Read/write memory access. Note that this is very slow as it copies the
* element between the GPU and the CPU
*
* @param index Element index
*/
inline viennacl::entry_proxy<T> operator[](index_t index)
{
return viennacl::entry_proxy<T>(offset+index, vector);
}

private:
void init();

public:
/** Memory segment holding the data for the vector */
VCLMemoryArray vector;

/** Offset for the memory segment, i.e the data of the vector
* starts at vector+offset
*/
index_t offset;

/** Vector length */
index_t vlen;
};

}

#endif
#endif
4 changes: 2 additions & 2 deletions src/shogun/lib/SGMatrix.h
Expand Up @@ -57,10 +57,10 @@ template<class T> class SGMatrix : public SGReferencedData
template <class Derived>
SGMatrix(Eigen::PlainObjectBase<Derived>& mat)
: SGReferencedData(false), matrix(mat.data()),
num_rows(mat.rows()), num_cols(mat.cols()) { }
num_rows(mat.rows()), num_cols(mat.cols()) { }

/** Wraps an Eigen3 matrix around the data of this matrix */
operator Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>() const
operator Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >() const
{
return Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >(
matrix, num_rows, num_cols);
Expand Down

0 comments on commit db545fd

Please sign in to comment.