Files
loongoffice/sc/source/core/opencl/opbase.hxx
haochen 3ad748accd GPU Calc:Support nested formulae expansion for simple nested
Change-Id: If1ae42a5481cf76942ff1ac5e0ee31a94159badd
2014-06-17 07:43:59 +02:00

299 lines
9.7 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_SC_SOURCE_CORE_OPENCL_OPBASE_HXX
#define INCLUDED_SC_SOURCE_CORE_OPENCL_OPBASE_HXX
#include <sal/log.hxx>
#include "clcc/clew.h"
#include <formula/token.hxx>
#include <formula/vectortoken.hxx>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <set>
#define ISNAN
namespace sc { namespace opencl {
class FormulaTreeNode;
/// Exceptions
/// Failed in parsing
class UnhandledToken
{
public:
UnhandledToken(formula::FormulaToken *t,
const char *const m, std::string fn="", int ln=0):
mToken(t), mMessage(m), mFile(fn), mLineNumber(ln) {}
formula::FormulaToken *mToken;
std::string mMessage;
std::string mFile;
int mLineNumber;
};
/// Failed in marshaling
class OpenCLError
{
private:
const char *strerror(cl_int i)
{
#define CASE(val) case val: return #val
switch (i)
{
CASE(CL_SUCCESS);
CASE(CL_DEVICE_NOT_FOUND);
CASE(CL_DEVICE_NOT_AVAILABLE);
CASE(CL_COMPILER_NOT_AVAILABLE);
CASE(CL_MEM_OBJECT_ALLOCATION_FAILURE);
CASE(CL_OUT_OF_RESOURCES);
CASE(CL_OUT_OF_HOST_MEMORY);
CASE(CL_PROFILING_INFO_NOT_AVAILABLE);
CASE(CL_MEM_COPY_OVERLAP);
CASE(CL_IMAGE_FORMAT_MISMATCH);
CASE(CL_IMAGE_FORMAT_NOT_SUPPORTED);
CASE(CL_BUILD_PROGRAM_FAILURE);
CASE(CL_MAP_FAILURE);
CASE(CL_INVALID_VALUE);
CASE(CL_INVALID_DEVICE_TYPE);
CASE(CL_INVALID_PLATFORM);
CASE(CL_INVALID_DEVICE);
CASE(CL_INVALID_CONTEXT);
CASE(CL_INVALID_QUEUE_PROPERTIES);
CASE(CL_INVALID_COMMAND_QUEUE);
CASE(CL_INVALID_HOST_PTR);
CASE(CL_INVALID_MEM_OBJECT);
CASE(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR);
CASE(CL_INVALID_IMAGE_SIZE);
CASE(CL_INVALID_SAMPLER);
CASE(CL_INVALID_BINARY);
CASE(CL_INVALID_BUILD_OPTIONS);
CASE(CL_INVALID_PROGRAM);
CASE(CL_INVALID_PROGRAM_EXECUTABLE);
CASE(CL_INVALID_KERNEL_NAME);
CASE(CL_INVALID_KERNEL_DEFINITION);
CASE(CL_INVALID_KERNEL);
CASE(CL_INVALID_ARG_INDEX);
CASE(CL_INVALID_ARG_VALUE);
CASE(CL_INVALID_ARG_SIZE);
CASE(CL_INVALID_KERNEL_ARGS);
CASE(CL_INVALID_WORK_DIMENSION);
CASE(CL_INVALID_WORK_GROUP_SIZE);
CASE(CL_INVALID_WORK_ITEM_SIZE);
CASE(CL_INVALID_GLOBAL_OFFSET);
CASE(CL_INVALID_EVENT_WAIT_LIST);
CASE(CL_INVALID_EVENT);
CASE(CL_INVALID_OPERATION);
CASE(CL_INVALID_GL_OBJECT);
CASE(CL_INVALID_BUFFER_SIZE);
CASE(CL_INVALID_MIP_LEVEL);
CASE(CL_INVALID_GLOBAL_WORK_SIZE);
default:
return "Unknown OpenCL error code";
}
#undef CASE
}
public:
OpenCLError(cl_int err, std::string fn, int ln): mError(err),
mFile(fn), mLineNumber(ln)
{
SAL_INFO("sc.opencl", "OpenCLError:" << mError << ": " << strerror(mError));
}
cl_int mError;
std::string mFile;
int mLineNumber;
};
/// Inconsistent state
class Unhandled
{
public:
Unhandled(std::string fn="", int ln=0):
mFile(fn), mLineNumber(ln) {}
std::string mFile;
int mLineNumber;
};
typedef boost::shared_ptr<FormulaTreeNode> FormulaTreeNodeRef;
class FormulaTreeNode
{
public:
FormulaTreeNode(const formula::FormulaToken* ft): mpCurrentFormula(ft)
{
Children.reserve(8);
}
std::vector<FormulaTreeNodeRef> Children;
formula::FormulaToken *GetFormulaToken(void) const
{
return const_cast<formula::FormulaToken*>(mpCurrentFormula.get());
}
private:
formula::FormulaConstTokenRef mpCurrentFormula;
};
/// (Partially) abstract base class for an operand
class DynamicKernelArgument : boost::noncopyable
{
public:
DynamicKernelArgument(const std::string &s, FormulaTreeNodeRef ft);
const std::string &GetNameAsString(void) const { return mSymName; }
/// Generate declaration
virtual void GenDecl(std::stringstream &ss) const = 0;
/// When declared as input to a sliding window function
virtual void GenSlidingWindowDecl(std::stringstream &ss) const = 0;
/// When referenced in a sliding window function
virtual std::string GenSlidingWindowDeclRef(bool=false) const = 0;
/// When Mix, it will be called
virtual std::string GenDoubleSlidingWindowDeclRef(bool=false) const
{ return std::string(""); }
/// When Mix, it will be called
virtual std::string GenStringSlidingWindowDeclRef(bool=false) const
{ return std::string(""); }
virtual bool IsMixedArgument() const
{ return false; }
/// Generate use/references to the argument
virtual void GenDeclRef(std::stringstream &ss) const;
virtual void GenNumDeclRef(std::stringstream &ss) const{ss << ",";}
virtual void GenStringDeclRef(std::stringstream &ss) const{ss << ",";}
/// Create buffer and pass the buffer to a given kernel
virtual size_t Marshal(cl_kernel, int, int, cl_program) = 0;
virtual ~DynamicKernelArgument() {}
virtual void GenSlidingWindowFunction(std::stringstream &) {}
const std::string &GetSymName(void) const { return mSymName; }
formula::FormulaToken *GetFormulaToken(void) const;
virtual size_t GetWindowSize(void) const = 0;
virtual std::string DumpOpName(void) const { return std::string(""); }
virtual void DumpInlineFun(std::set<std::string>& ,
std::set<std::string>& ) const {}
const std::string& GetName(void) const { return mSymName; }
virtual bool NeedParallelReduction(void) const { return false; }
protected:
std::string mSymName;
FormulaTreeNodeRef mFormulaTree;
};
/// Holds an input (read-only) argument reference to a SingleVectorRef.
/// or a DoubleVectorRef for non-sliding-window argument of complex functions
/// like SumOfProduct
/// In most of the cases the argument is introduced
/// by a Push operation in the given RPN.
class VectorRef : public DynamicKernelArgument
{
public:
VectorRef(const std::string &s, FormulaTreeNodeRef ft, int index = 0);
const std::string &GetNameAsString(void) const { return mSymName; }
/// Generate declaration
virtual void GenDecl(std::stringstream &ss) const SAL_OVERRIDE;
/// When declared as input to a sliding window function
virtual void GenSlidingWindowDecl(std::stringstream &ss) const SAL_OVERRIDE;
/// When referenced in a sliding window function
virtual std::string GenSlidingWindowDeclRef(bool=false) const SAL_OVERRIDE;
/// Create buffer and pass the buffer to a given kernel
virtual size_t Marshal(cl_kernel, int, int, cl_program) SAL_OVERRIDE;
virtual ~VectorRef();
virtual void GenSlidingWindowFunction(std::stringstream &) SAL_OVERRIDE {}
const std::string &GetSymName(void) const { return mSymName; }
virtual size_t GetWindowSize(void) const SAL_OVERRIDE;
virtual std::string DumpOpName(void) const SAL_OVERRIDE { return std::string(""); }
virtual void DumpInlineFun(std::set<std::string>& ,
std::set<std::string>& ) const SAL_OVERRIDE {}
const std::string& GetName(void) const { return mSymName; }
virtual cl_mem GetCLBuffer(void) const { return mpClmem; }
virtual bool NeedParallelReduction(void) const SAL_OVERRIDE { return false; }
protected:
// Used by marshaling
cl_mem mpClmem;
// index in multiple double vector refs that have multiple ranges
const int mnIndex;
};
/// Abstract class for code generation
class OpBase
{
public:
typedef std::vector<std::string> ArgVector;
typedef std::vector<std::string>::iterator ArgVectorIter;
virtual std::string GetBottom(void) {return "";};
virtual std::string Gen2(const std::string &/*lhs*/,
const std::string &/*rhs*/) const {return "";}
virtual std::string Gen(ArgVector& /*argVector*/){return "";};
virtual std::string BinFuncName(void)const {return "";};
virtual void BinInlineFun(std::set<std::string>& ,
std::set<std::string>& ) {}
virtual bool takeString() const = 0;
virtual bool takeNumeric() const = 0;
//Continue process 'Zero' or Not(like OpMul, not continue process when meet
// 'Zero'
virtual bool ZeroReturnZero() {return false;}
virtual ~OpBase() {}
};
class SlidingFunctionBase : public OpBase
{
public:
typedef boost::shared_ptr<DynamicKernelArgument> SubArgument;
typedef std::vector<SubArgument> SubArguments;
virtual void GenSlidingWindowFunction(std::stringstream &,
const std::string&, SubArguments &) = 0;
virtual ~SlidingFunctionBase() {};
};
class Normal: public SlidingFunctionBase
{
public:
virtual void GenSlidingWindowFunction(std::stringstream &ss,
const std::string &sSymName, SubArguments &vSubArguments) SAL_OVERRIDE;
virtual bool takeString() const SAL_OVERRIDE { return false; }
virtual bool takeNumeric() const SAL_OVERRIDE { return true; }
};
class CheckVariables:public Normal
{
public:
void GenTmpVariables(std::stringstream &ss, SubArguments &vSubArguments);
void CheckSubArgumentIsNan(std::stringstream &ss,
SubArguments &vSubArguments, int argumentNum);
void CheckAllSubArgumentIsNan(std::stringstream &ss,
SubArguments &vSubArguments);
// only check isNan
void CheckSubArgumentIsNan2(std::stringstream &ss,
SubArguments &vSubArguments, int argumentNum, std::string p);
void UnrollDoubleVector(std::stringstream &ss,
std::stringstream &unrollstr, const formula::DoubleVectorRefToken* pCurDVR,
int nCurWindowSize);
};
}}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */