git-svn-id: svn://db.shs.com.ru/pip@559 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5
This commit is contained in:
@@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 2.6)
|
|||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
|
include(PIPMacros.cmake)
|
||||||
|
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
@@ -33,7 +34,7 @@ set(PIP_SRC_CRYPT "src_crypt")
|
|||||||
set(PIP_SRC_COMPRESS "src_compress")
|
set(PIP_SRC_COMPRESS "src_compress")
|
||||||
set(PIP_SRC_USB "src_usb")
|
set(PIP_SRC_USB "src_usb")
|
||||||
set(PIP_SRC_FFTW "src_fftw")
|
set(PIP_SRC_FFTW "src_fftw")
|
||||||
#set(PIP_SRC_RESOURCES "src_resources")
|
set(PIP_SRC_OPENCL "src_opencl")
|
||||||
set(PIP_LIBS_TARGETS pip)
|
set(PIP_LIBS_TARGETS pip)
|
||||||
set(LIBS_MAIN)
|
set(LIBS_MAIN)
|
||||||
set(LIBS_STATUS)
|
set(LIBS_STATUS)
|
||||||
@@ -86,7 +87,7 @@ endif()
|
|||||||
# Sources
|
# Sources
|
||||||
|
|
||||||
# Main lib
|
# Main lib
|
||||||
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io" "console" "math" "code" "geo" "resources")
|
set(PIP_FOLDERS "." "core" "containers" "thread" "system" "io" "console" "math" "code" "geo" "resources" "opencl")
|
||||||
include_directories("${PIP_SRC_MAIN}")
|
include_directories("${PIP_SRC_MAIN}")
|
||||||
foreach(F ${PIP_FOLDERS})
|
foreach(F ${PIP_FOLDERS})
|
||||||
include_directories("${PIP_SRC_MAIN}/${F}")
|
include_directories("${PIP_SRC_MAIN}/${F}")
|
||||||
@@ -105,8 +106,8 @@ gather_src("${PIP_SRC_USB}" CPP_LIB_USB HDRS PHDRS)
|
|||||||
# FFTW lib
|
# FFTW lib
|
||||||
gather_src("${PIP_SRC_FFTW}" CPP_LIB_FFTW HDRS PHDRS)
|
gather_src("${PIP_SRC_FFTW}" CPP_LIB_FFTW HDRS PHDRS)
|
||||||
|
|
||||||
# Resources lib
|
# OpenCL lib
|
||||||
#gather_src("${PIP_SRC_RESOURCES}" CPP_LIB_RESOURCES HDRS PHDRS)
|
gather_src("${PIP_SRC_OPENCL}" CPP_LIB_OPENCL HDRS PHDRS)
|
||||||
|
|
||||||
|
|
||||||
# Check Bessel functions
|
# Check Bessel functions
|
||||||
@@ -361,10 +362,23 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Add resource system
|
# Check if PIP support OpenCL
|
||||||
#add_library(pip_resources SHARED ${CPP_LIB_RESOURCES})
|
find_package(OpenCL QUIET)
|
||||||
#target_link_libraries(pip_resources pip )
|
if(OpenCL_FOUND)
|
||||||
#list(APPEND PIP_LIBS_TARGETS pip_resources)
|
message(STATUS "Building with OpenCL support")
|
||||||
|
include_directories(${OpenCL_INCLUDE_DIRS})
|
||||||
|
add_definitions(-DPIP_OPENCL)
|
||||||
|
pip_resources(CL_RES "src_opencl/resources.conf")
|
||||||
|
add_library(pip_opencl SHARED ${CPP_LIB_OPENCL} ${CL_RES})
|
||||||
|
add_dependencies(pip_opencl pip_rc)
|
||||||
|
target_link_libraries(pip_opencl pip ${OpenCL_LIBRARIES})
|
||||||
|
list(APPEND LIBS_STATUS OpenCL)
|
||||||
|
list(APPEND PIP_LIBS_TARGETS pip_opencl)
|
||||||
|
set(OpenCL_FOUND ${OpenCL_LIBRARIES})
|
||||||
|
else()
|
||||||
|
message(STATUS "Building without OpenCL support")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Test program
|
# Test program
|
||||||
@@ -386,6 +400,7 @@ if(LIB)
|
|||||||
#message("${STDLIB}")
|
#message("${STDLIB}")
|
||||||
if (STDLIB)
|
if (STDLIB)
|
||||||
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator")
|
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/code_model_generator")
|
||||||
|
file(COPY "${STDLIB}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/utils/resources_compiler")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -347,6 +347,12 @@ bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
|
|||||||
true;
|
true;
|
||||||
#else
|
#else
|
||||||
false;
|
false;
|
||||||
|
#endif
|
||||||
|
case OpenCL: return
|
||||||
|
#ifdef PIP_OPENCL
|
||||||
|
true;
|
||||||
|
#else
|
||||||
|
false;
|
||||||
#endif
|
#endif
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
@@ -364,6 +370,7 @@ PIStringList PIInit::buildOptions() {
|
|||||||
if (isBuildOptionEnabled(IntrospectionThreads)) ret << "IntrospectionThreads";
|
if (isBuildOptionEnabled(IntrospectionThreads)) ret << "IntrospectionThreads";
|
||||||
if (isBuildOptionEnabled(FFTW)) ret << "FFTW";
|
if (isBuildOptionEnabled(FFTW)) ret << "FFTW";
|
||||||
if (isBuildOptionEnabled(Compress)) ret << "Compress";
|
if (isBuildOptionEnabled(Compress)) ret << "Compress";
|
||||||
|
if (isBuildOptionEnabled(OpenCL)) ret << "OpenCL";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
IntrospectionThreads /*! Threads introspection */ = 0x20,
|
IntrospectionThreads /*! Threads introspection */ = 0x20,
|
||||||
FFTW /*! FFTW3 support */ = 0x40,
|
FFTW /*! FFTW3 support */ = 0x40,
|
||||||
Compress /*! Zlib compression support */ = 0x80,
|
Compress /*! Zlib compression support */ = 0x80,
|
||||||
|
OpenCL /*! OpenCL support */ = 0x100,
|
||||||
};
|
};
|
||||||
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
|
static PIInit * instance() {return __PIInit_Initializer__::__instance__;}
|
||||||
static bool isBuildOptionEnabled(BuildOption o);
|
static bool isBuildOptionEnabled(BuildOption o);
|
||||||
|
|||||||
175
src_main/opencl/piopencl.h
Normal file
175
src_main/opencl/piopencl.h
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#ifndef PIOPENCL_H
|
||||||
|
#define PIOPENCL_H
|
||||||
|
|
||||||
|
#include "pivariant.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PIOpenCL {
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct KernelArg;
|
||||||
|
struct Device;
|
||||||
|
struct Platform;
|
||||||
|
class Context;
|
||||||
|
class Program;
|
||||||
|
class Kernel;
|
||||||
|
|
||||||
|
typedef PIVector<Device> DeviceList;
|
||||||
|
|
||||||
|
enum AddressQualifier {
|
||||||
|
AddressGlobal,
|
||||||
|
AddressLocal,
|
||||||
|
AddressConstant,
|
||||||
|
AddressPrivate,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AccessQualifier {
|
||||||
|
AccessReadOnly,
|
||||||
|
AccessWriteOnly,
|
||||||
|
AccessReadWrite,
|
||||||
|
AccessNone,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TypeQualifier {
|
||||||
|
TypeConst,
|
||||||
|
TypeRestrict,
|
||||||
|
TypeVolatile,
|
||||||
|
TypeNone,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ArgType {
|
||||||
|
Char = 1,
|
||||||
|
UChar,
|
||||||
|
Short,
|
||||||
|
UShort,
|
||||||
|
Int,
|
||||||
|
UInt,
|
||||||
|
Long,
|
||||||
|
ULong,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KernelArg {
|
||||||
|
KernelArg();
|
||||||
|
AddressQualifier address_qualifier;
|
||||||
|
AccessQualifier access_qualifier;
|
||||||
|
TypeQualifier type_qualifier;
|
||||||
|
PIString arg_name;
|
||||||
|
PIString type_name;
|
||||||
|
PIString base_type_name;
|
||||||
|
bool is_pointer;
|
||||||
|
ArgType arg_type;
|
||||||
|
int dims;
|
||||||
|
private:
|
||||||
|
friend class Kernel;
|
||||||
|
void init(void * _k, uint index);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Device {
|
||||||
|
Device() {id = platform_id = 0; max_compute_units = max_clock_frequency = 0; max_memory_size = 0;}
|
||||||
|
bool isValid() const {return id != 0;}
|
||||||
|
PIString displayText() const {return name.trimmed() + " (" + device_version.trimmed() + ")";}
|
||||||
|
void * id;
|
||||||
|
void * platform_id;
|
||||||
|
PIString name;
|
||||||
|
PIString vendor;
|
||||||
|
PIString device_version;
|
||||||
|
PIString driver_version;
|
||||||
|
int max_compute_units;
|
||||||
|
int max_clock_frequency;
|
||||||
|
ullong max_memory_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Platform {
|
||||||
|
Platform() {id = 0;}
|
||||||
|
bool isValid() const {return id != 0;}
|
||||||
|
PIString displayText() const {return name.trimmed() + " (" + version.trimmed() + ", " + profile.trimmed() + ")";}
|
||||||
|
void * id;
|
||||||
|
PIString name;
|
||||||
|
PIString vendor;
|
||||||
|
PIString profile;
|
||||||
|
PIString version;
|
||||||
|
PIStringList extensions;
|
||||||
|
PIVector<Device> devices;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Context {
|
||||||
|
friend class Program;
|
||||||
|
public:
|
||||||
|
~Context();
|
||||||
|
static Context * create(const DeviceList & dl);
|
||||||
|
static Context * create(const Device & d) {return create(DeviceList() << d);}
|
||||||
|
Program * createProgram(const PIString & source, PIString * error = 0);
|
||||||
|
private:
|
||||||
|
Context();
|
||||||
|
void zero();
|
||||||
|
void deletePrograms();
|
||||||
|
PIVector<Program * > programs_;
|
||||||
|
PRIVATE_DECLARATION
|
||||||
|
};
|
||||||
|
|
||||||
|
class Program {
|
||||||
|
friend class Context;
|
||||||
|
friend class Kernel;
|
||||||
|
public:
|
||||||
|
~Program();
|
||||||
|
const PIString & sourceCode() const {return source_;}
|
||||||
|
const Kernel * kernel(int index = 0) const {return kernels_[index];}
|
||||||
|
const PIVector<Kernel * > & kernels() const {return kernels_;}
|
||||||
|
private:
|
||||||
|
Program();
|
||||||
|
void zero();
|
||||||
|
bool initKernels(PIVector<void*> kerns);
|
||||||
|
Context * context_;
|
||||||
|
PIString source_;
|
||||||
|
PIVector<Kernel * > kernels_;
|
||||||
|
PRIVATE_DECLARATION
|
||||||
|
};
|
||||||
|
|
||||||
|
class Kernel {
|
||||||
|
friend class Program;
|
||||||
|
public:
|
||||||
|
const PIString & name() const {return name_;}
|
||||||
|
const PIVector<KernelArg> & args() const {return args_;}
|
||||||
|
template <typename T> bool setArgValue(int index, const T & value) {return setArgValueV(index, PIVariant::fromValue(value));}
|
||||||
|
template <typename T> bool setArgValue(const PIString & arg, const T & value) {return setArgValue(argIndex(arg), value);}
|
||||||
|
private:
|
||||||
|
Kernel();
|
||||||
|
~Kernel();
|
||||||
|
void zero();
|
||||||
|
bool init();
|
||||||
|
bool setArgValueV(int index, const PIVariant & value);
|
||||||
|
int argIndex(const PIString & an) const;
|
||||||
|
KernelArg argByName(const PIString & an) const;
|
||||||
|
Context * context_;
|
||||||
|
Program * program_;
|
||||||
|
PIString name_;
|
||||||
|
PIVector<KernelArg> args_;
|
||||||
|
PRIVATE_DECLARATION
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init();
|
||||||
|
static const PIVector<Platform> & platforms();
|
||||||
|
static const PIVector<Device> devices();
|
||||||
|
static Device deviceByID(void * id);
|
||||||
|
static PIString prepareProgram(const PIString & prog);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PIString prog_header;
|
||||||
|
PIOpenCL() {;}
|
||||||
|
class Initializer {
|
||||||
|
public:
|
||||||
|
Initializer();
|
||||||
|
static Initializer * instance();
|
||||||
|
void init();
|
||||||
|
PIVector<Platform> platforms_;
|
||||||
|
bool inited_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PICout operator <<(PICout s, const PIOpenCL::KernelArg & v);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PIOPENCL_H
|
||||||
318
src_opencl/3rd/clcomplex.h
Normal file
318
src_opencl/3rd/clcomplex.h
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
//---------------------------------------------------------------------------//
|
||||||
|
// MIT License
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017 StreamComputing
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//---------------------------------------------------------------------------//
|
||||||
|
|
||||||
|
#ifndef OPENCL_COMPLEX_MATH
|
||||||
|
#define OPENCL_COMPLEX_MATH
|
||||||
|
|
||||||
|
#define CONCAT(x, y) x##y
|
||||||
|
#define FNAME(name, sufix) c##name##sufix
|
||||||
|
|
||||||
|
// float2
|
||||||
|
#define clrealf(complex) complex.x;
|
||||||
|
#define climagf(complex) complex.y;
|
||||||
|
|
||||||
|
// double2
|
||||||
|
#define clreal(complex) complex.x;
|
||||||
|
#define climag(complex) complex.y;
|
||||||
|
|
||||||
|
#define OPENCL_COMPLEX_MATH_FUNCS(complex_type, real_type, func_sufix, math_consts_sufix) \
|
||||||
|
complex_type CONCAT(complex, func_sufix)(real_type r, real_type i) \
|
||||||
|
{ \
|
||||||
|
return (complex_type)(r, i); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(add, func_sufix)(complex_type x, complex_type y) \
|
||||||
|
{ \
|
||||||
|
return x + y; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(sub, func_sufix)(complex_type x, complex_type y) \
|
||||||
|
{ \
|
||||||
|
return x - y; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(add_real, func_sufix)(complex_type z, real_type r) \
|
||||||
|
{ \
|
||||||
|
return (complex_type)(z.x + r, z.y); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(sub_real, func_sufix)(complex_type z, real_type r) \
|
||||||
|
{ \
|
||||||
|
return (complex_type)(z.x - r, z.y); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
real_type FNAME(abs, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return length(z); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
real_type FNAME(arg, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return atan2(z.y, z.x); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(mul, func_sufix)(complex_type z1, complex_type z2) \
|
||||||
|
{ \
|
||||||
|
real_type x1 = z1.x; \
|
||||||
|
real_type y1 = z1.y; \
|
||||||
|
real_type x2 = z2.x; \
|
||||||
|
real_type y2 = z2.y; \
|
||||||
|
return (complex_type)(x1 * x2 - y1 * y2, x1 * y2 + x2 * y1); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(div, func_sufix)(complex_type z1, complex_type z2) \
|
||||||
|
{ \
|
||||||
|
real_type x1 = z1.x; \
|
||||||
|
real_type y1 = z1.y; \
|
||||||
|
real_type x2 = z2.x; \
|
||||||
|
real_type y2 = z2.y; \
|
||||||
|
real_type iabs_z2 = CONCAT(1.0, func_sufix) / FNAME(abs, func_sufix)(z2); \
|
||||||
|
return (complex_type)( \
|
||||||
|
((x1 * x2 * iabs_z2) + (y1 * y2 * iabs_z2)) * iabs_z2, \
|
||||||
|
((y1 * x2 * iabs_z2) - (x1 * y2 * iabs_z2)) * iabs_z2 \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(mul_real, func_sufix)(complex_type z, real_type r) \
|
||||||
|
{ \
|
||||||
|
return z * r; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(div_real, func_sufix)(complex_type z, real_type r) \
|
||||||
|
{ \
|
||||||
|
return z / r; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(conj, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return (complex_type)(z.x, -z.y); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(proj, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
if(isinf(z.x) || isinf(z.y)) \
|
||||||
|
{ \
|
||||||
|
return (complex_type)(INFINITY, (copysign(CONCAT(0.0, func_sufix), z.y))); \
|
||||||
|
} \
|
||||||
|
return z; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
real_type FNAME(norm, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
/* Returns the squared magnitude of the complex number z. */ \
|
||||||
|
/* The norm calculated by this function is also known as */ \
|
||||||
|
/* field norm or absolute square. */ \
|
||||||
|
real_type x = z.x; \
|
||||||
|
real_type y = z.y; \
|
||||||
|
return x * x + y * y; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(polar, func_sufix)(real_type r, real_type theta) \
|
||||||
|
{ \
|
||||||
|
/* Returns a complex number with magnitude r and phase angle theta. */ \
|
||||||
|
return (complex_type)(r * cos(theta), r * sin(theta)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(exp, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
/* The complex exponential function e^z for z = x+i*y */ \
|
||||||
|
/* equals to e^x * cis(y), */ \
|
||||||
|
/* or, e^x * (cos(y) + i*sin(y)) */ \
|
||||||
|
real_type expx = exp(z.x); \
|
||||||
|
return (complex_type)(expx * cos(z.y), expx * sin(z.y)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(log, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
/* log(z) = log(abs(z)) + i * arg(z) */ \
|
||||||
|
return (complex_type)(log(FNAME(abs, func_sufix)(z)),FNAME(arg, func_sufix)(z)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(log10, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return FNAME(log, func_sufix)(z) / log(CONCAT(10.0, func_sufix)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(pow, func_sufix)(complex_type z1, complex_type z2) \
|
||||||
|
{ \
|
||||||
|
/* (z1)^(z2) = exp(z2 * log(z1)) = cexp(mul(z2, clog(z1))) */ \
|
||||||
|
return \
|
||||||
|
FNAME(exp, func_sufix)( \
|
||||||
|
FNAME(mul, func_sufix)( \
|
||||||
|
z2, \
|
||||||
|
FNAME(log, func_sufix)(z1) \
|
||||||
|
) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(sqrt, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
/* */ \
|
||||||
|
real_type x = z.x; \
|
||||||
|
real_type y = z.y; \
|
||||||
|
if(x == CONCAT(0.0, func_sufix)) \
|
||||||
|
{ \
|
||||||
|
real_type t = sqrt(fabs(y) / 2); \
|
||||||
|
return (complex_type)(t, y < CONCAT(0.0, func_sufix) ? -t : t); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
real_type t = sqrt(2 * FNAME(abs, func_sufix)(z) + fabs(x)); \
|
||||||
|
real_type u = t / 2; \
|
||||||
|
return x > CONCAT(0.0, func_sufix) \
|
||||||
|
? (complex_type)(u, y / t) \
|
||||||
|
: (complex_type)(fabs(y) / t, y < CONCAT(0.0, func_sufix) ? -u : u); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(sin, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type x = z.x; \
|
||||||
|
const real_type y = z.y; \
|
||||||
|
return (complex_type)(sin(x) * cosh(y), cos(x) * sinh(y)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(sinh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type x = z.x; \
|
||||||
|
const real_type y = z.y; \
|
||||||
|
return (complex_type)(sinh(x) * cos(y), cosh(x) * sin(y)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(cos, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type x = z.x; \
|
||||||
|
const real_type y = z.y; \
|
||||||
|
return (complex_type)(cos(x) * cosh(y), -sin(x) * sinh(y)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(cosh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type x = z.x; \
|
||||||
|
const real_type y = z.y; \
|
||||||
|
return (complex_type)(cosh(x) * cos(y), sinh(x) * sin(y)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(tan, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return FNAME(div, func_sufix)( \
|
||||||
|
FNAME(sin, func_sufix)(z), \
|
||||||
|
FNAME(cos, func_sufix)(z) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(tanh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return FNAME(div, func_sufix)( \
|
||||||
|
FNAME(sinh, func_sufix)(z), \
|
||||||
|
FNAME(cosh, func_sufix)(z) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(asinh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
complex_type t = (complex_type)( \
|
||||||
|
(z.x - z.y) * (z.x + z.y) + CONCAT(1.0, func_sufix), \
|
||||||
|
CONCAT(2.0, func_sufix) * z.x * z.y \
|
||||||
|
); \
|
||||||
|
t = FNAME(sqrt, func_sufix)(t) + z; \
|
||||||
|
return FNAME(log, func_sufix)(t); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(asin, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
complex_type t = (complex_type)(-z.y, z.x); \
|
||||||
|
t = FNAME(asinh, func_sufix)(t); \
|
||||||
|
return (complex_type)(t.y, -t.x); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(acosh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
return \
|
||||||
|
CONCAT(2.0, func_sufix) * FNAME(log, func_sufix)( \
|
||||||
|
FNAME(sqrt, func_sufix)( \
|
||||||
|
CONCAT(0.5, func_sufix) * (z + CONCAT(1.0, func_sufix)) \
|
||||||
|
) \
|
||||||
|
+ FNAME(sqrt, func_sufix)( \
|
||||||
|
CONCAT(0.5, func_sufix) * (z - CONCAT(1.0, func_sufix)) \
|
||||||
|
) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(acos, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
complex_type t = FNAME(asin, func_sufix)(z);\
|
||||||
|
return (complex_type)( \
|
||||||
|
CONCAT(M_PI_2, math_consts_sufix) - t.x, -t.y \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(atanh, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type zy2 = z.y * z.y; \
|
||||||
|
real_type n = CONCAT(1.0, func_sufix) + z.x; \
|
||||||
|
real_type d = CONCAT(1.0, func_sufix) - z.x; \
|
||||||
|
n = zy2 + n * n; \
|
||||||
|
d = zy2 + d * d; \
|
||||||
|
return (complex_type)( \
|
||||||
|
CONCAT(0.25, func_sufix) * (log(n) - log(d)), \
|
||||||
|
CONCAT(0.5, func_sufix) * atan2( \
|
||||||
|
CONCAT(2.0, func_sufix) * z.y, \
|
||||||
|
CONCAT(1.0, func_sufix) - zy2 - (z.x * z.x) \
|
||||||
|
) \
|
||||||
|
); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
complex_type FNAME(atan, func_sufix)(complex_type z) \
|
||||||
|
{ \
|
||||||
|
const real_type zx2 = z.x * z.x; \
|
||||||
|
real_type n = z.y + CONCAT(1.0, func_sufix); \
|
||||||
|
real_type d = z.y - CONCAT(1.0, func_sufix); \
|
||||||
|
n = zx2 + n * n; \
|
||||||
|
d = zx2 + d * d; \
|
||||||
|
return (complex_type)( \
|
||||||
|
CONCAT(0.5, func_sufix) * atan2( \
|
||||||
|
CONCAT(2.0, func_sufix) * z.x, \
|
||||||
|
CONCAT(1.0, func_sufix) - zx2 - (z.y * z.y) \
|
||||||
|
), \
|
||||||
|
CONCAT(0.25, func_sufix) * (log(n / d)) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
// float complex
|
||||||
|
typedef float2 cfloat;
|
||||||
|
OPENCL_COMPLEX_MATH_FUNCS(float2, float, f, _F)
|
||||||
|
|
||||||
|
// double complex
|
||||||
|
#ifdef cl_khr_fp64
|
||||||
|
# ifdef OPENCL_COMPLEX_MATH_USE_DOUBLE
|
||||||
|
# pragma OPENCL EXTENSION cl_khr_fp64 : enable
|
||||||
|
typedef double2 cdouble;
|
||||||
|
OPENCL_COMPLEX_MATH_FUNCS(double2, double, , )
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef FNAME
|
||||||
|
#undef CONCAT
|
||||||
|
#endif // OPENCL_COMPLEX_MATH
|
||||||
452
src_opencl/piopencl.cpp
Normal file
452
src_opencl/piopencl.cpp
Normal file
@@ -0,0 +1,452 @@
|
|||||||
|
#include "piopencl.h"
|
||||||
|
#include "CL/cl.h"
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE_DEFINITION_START(PIOpenCL::Context)
|
||||||
|
cl_context context;
|
||||||
|
cl_command_queue queue;
|
||||||
|
PIVector<cl_device_id> devices;
|
||||||
|
PRIVATE_DEFINITION_END(PIOpenCL::Context)
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE_DEFINITION_START(PIOpenCL::Program)
|
||||||
|
cl_program program;
|
||||||
|
PRIVATE_DEFINITION_END(PIOpenCL::Program)
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE_DEFINITION_START(PIOpenCL::Kernel)
|
||||||
|
cl_kernel kernel;
|
||||||
|
PRIVATE_DEFINITION_END(PIOpenCL::Kernel)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::init() {
|
||||||
|
Initializer::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PIVector<PIOpenCL::Platform> & PIOpenCL::platforms() {
|
||||||
|
return Initializer::instance()->platforms_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PIVector<PIOpenCL::Device> PIOpenCL::devices() {
|
||||||
|
PIVector<PIOpenCL::Device> ret;
|
||||||
|
PIVector<PIOpenCL::Platform> pl = platforms();
|
||||||
|
piForeachC (PIOpenCL::Platform & p, pl)
|
||||||
|
ret << p.devices;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Device PIOpenCL::deviceByID(void * id) {
|
||||||
|
PIVector<PIOpenCL::Platform> pl = platforms();
|
||||||
|
piForeachC (PIOpenCL::Platform & p, pl) {
|
||||||
|
piForeachC (PIOpenCL::Device & d, p.devices) {
|
||||||
|
if (d.id == id) return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Device();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Initializer::Initializer() {
|
||||||
|
inited_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Initializer * PIOpenCL::Initializer::instance() {
|
||||||
|
static PIOpenCL::Initializer * ret = new PIOpenCL::Initializer();
|
||||||
|
ret->init();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::Initializer::init() {
|
||||||
|
if (inited_) return;
|
||||||
|
inited_ = true;
|
||||||
|
piCout << "init OpenCL";
|
||||||
|
platforms_.clear();
|
||||||
|
const int max_size = 256;
|
||||||
|
cl_platform_id cl_platforms[max_size];
|
||||||
|
char buffer[10240];
|
||||||
|
cl_int ret = 0;
|
||||||
|
cl_uint plat_num = 0;
|
||||||
|
ret = clGetPlatformIDs(max_size, cl_platforms, &plat_num);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL] Error: OpenCL platforms not found!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (uint i = 0; i < plat_num; i++) {
|
||||||
|
Platform p;
|
||||||
|
p.id = cl_platforms[i];
|
||||||
|
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_NAME, sizeof(buffer), buffer, 0);
|
||||||
|
p.name = buffer;
|
||||||
|
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_VENDOR, sizeof(buffer), buffer, 0);
|
||||||
|
p.vendor = buffer;
|
||||||
|
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_PROFILE, sizeof(buffer), buffer, 0);
|
||||||
|
p.profile = buffer;
|
||||||
|
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_VERSION, sizeof(buffer), buffer, 0);
|
||||||
|
p.version = buffer;
|
||||||
|
clGetPlatformInfo(cl_platforms[i], CL_PLATFORM_EXTENSIONS, sizeof(buffer), buffer, 0);
|
||||||
|
p.extensions = PIString(buffer).trim().split(" ");
|
||||||
|
|
||||||
|
uint dev_num = 0;
|
||||||
|
cl_device_id cl_devices[max_size];
|
||||||
|
ret = clGetDeviceIDs(cl_platforms[i], CL_DEVICE_TYPE_ALL, max_size, cl_devices, &dev_num);
|
||||||
|
if (ret == 0) {
|
||||||
|
//piCout << "[OpenCLBlock] OpenCL cl_devices on platform" + PIString::fromNumber(i) + "found:" << dev_num;
|
||||||
|
for (uint j = 0; j < dev_num; j++) {
|
||||||
|
uint buf_uint = 0;
|
||||||
|
ullong buf_ulong = 0;
|
||||||
|
Device d;
|
||||||
|
d.id = cl_devices[j];
|
||||||
|
d.platform_id = p.id;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_NAME, sizeof(buffer), buffer, 0);
|
||||||
|
d.name = buffer;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_VENDOR, sizeof(buffer), buffer, 0);
|
||||||
|
d.vendor = buffer;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_VERSION, sizeof(buffer), buffer, 0);
|
||||||
|
d.device_version = buffer;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DRIVER_VERSION, sizeof(buffer), buffer, 0);
|
||||||
|
d.driver_version = buffer;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf_uint), &buf_uint, 0);
|
||||||
|
d.max_compute_units = buf_uint;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf_uint), &buf_uint, 0);
|
||||||
|
d.max_clock_frequency = buf_uint;
|
||||||
|
clGetDeviceInfo(cl_devices[j], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buf_ulong), &buf_ulong, 0);
|
||||||
|
d.max_memory_size = buf_ulong;
|
||||||
|
p.devices << d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
platforms_ << p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Context::Context() {
|
||||||
|
zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Context::~Context() {
|
||||||
|
piCout << "destroy context" << this;
|
||||||
|
deletePrograms();
|
||||||
|
if (PRIVATE->queue)
|
||||||
|
clReleaseCommandQueue(PRIVATE->queue);
|
||||||
|
if (PRIVATE->context)
|
||||||
|
clReleaseContext(PRIVATE->context);
|
||||||
|
zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::Context::zero() {
|
||||||
|
programs_.clear();
|
||||||
|
PRIVATE->context = 0;
|
||||||
|
PRIVATE->queue = 0;
|
||||||
|
PRIVATE->devices.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::Context::deletePrograms() {
|
||||||
|
piCout << "context: delete" << programs_.size() << "progs";
|
||||||
|
PIVector<Program * > ptdl = programs_;
|
||||||
|
programs_.clear();
|
||||||
|
piForeach (Program * p, ptdl) {
|
||||||
|
if (p) delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Context * PIOpenCL::Context::create(const PIOpenCL::DeviceList & dl) {
|
||||||
|
if (dl.isEmpty()) return 0;
|
||||||
|
Context * rc = 0;
|
||||||
|
PIVector<cl_device_id> cldl;
|
||||||
|
for (int i = 0; i < dl.size_s(); ++i)
|
||||||
|
if (dl[i].isValid())
|
||||||
|
cldl << (cl_device_id)dl[i].id;
|
||||||
|
//piCout << "create for" << dl[0].name << "...";
|
||||||
|
cl_int ret = 0;
|
||||||
|
cl_context con = clCreateContext(0, cldl.size_s(), cldl.data(), 0, 0, &ret);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clCreateContext error" << ret;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cl_command_queue comq = clCreateCommandQueue(con, cldl[0], 0, &ret);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clCreateCommandQueue error" << ret;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
piCout << "create done for" << dl[0].name;
|
||||||
|
rc = new Context();
|
||||||
|
rc->PRIVATEWB->context = con;
|
||||||
|
rc->PRIVATEWB->queue = comq;
|
||||||
|
rc->PRIVATEWB->devices = cldl;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Program * PIOpenCL::Context::createProgram(const PIString & source, PIString * error) {
|
||||||
|
if (error) error->clear();
|
||||||
|
if (source.isEmpty()) {
|
||||||
|
if (error) (*error) = "Empty program!";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const char * csrc = source.dataAscii();
|
||||||
|
size_t src_size = source.size();
|
||||||
|
cl_int ret = 0;
|
||||||
|
cl_program prog = clCreateProgramWithSource(PRIVATE->context, 1, &csrc, &src_size, &ret);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clCreateProgramWithSource error" << ret;
|
||||||
|
if (error) (*error) << "clCreateProgramWithSource error " << ret;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = clBuildProgram(prog, 0, 0, "-cl-kernel-arg-info", 0, 0);
|
||||||
|
char buffer[10240];
|
||||||
|
clGetProgramBuildInfo(prog, PRIVATE->devices[0], CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
clReleaseProgram(prog);
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clBuildProgram error" << ret;// << ":" << buffer;
|
||||||
|
if (error) (*error) = buffer;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t uret = 0;
|
||||||
|
ret = clGetProgramInfo(prog, CL_PROGRAM_NUM_KERNELS, sizeof(uret), &uret, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
clReleaseProgram(prog);
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clGetProgramInfo error" << ret;
|
||||||
|
if (error) (*error) = "Can`t retrieve CL_PROGRAM_NUM_KERNELS";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const int ccnt = 10240;
|
||||||
|
char knames[ccnt];
|
||||||
|
ret = clGetProgramInfo(prog, CL_PROGRAM_KERNEL_NAMES, ccnt, knames, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
clReleaseProgram(prog);
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clGetProgramInfo error" << ret;
|
||||||
|
if (error) (*error) = "Can`t retrieve CL_PROGRAM_KERNEL_NAMES";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
PIStringList knl = PIString(knames).trim().split(";");
|
||||||
|
PIVector<void*> kerns;
|
||||||
|
piForeachC (PIString & k, knl) {
|
||||||
|
cl_kernel kern = clCreateKernel(prog, k.dataAscii(), &ret);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Context]" << "clCreateKernel" << k << "error" << ret;
|
||||||
|
if (error) (*error) << "clCreateKernel(\"" << k << "\") error " << ret;
|
||||||
|
piForeach (void* _k, kerns)
|
||||||
|
clReleaseKernel((cl_kernel)_k);
|
||||||
|
clReleaseProgram(prog);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
kerns << kern;
|
||||||
|
}
|
||||||
|
//piCout << knl << kerns;
|
||||||
|
Program * rp = new Program();
|
||||||
|
rp->context_ = this;
|
||||||
|
rp->source_ = source;
|
||||||
|
rp->PRIVATEWB->program = prog;
|
||||||
|
if (!rp->initKernels(kerns)) {
|
||||||
|
delete rp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
programs_ << rp;
|
||||||
|
return rp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Program::Program() {
|
||||||
|
//piCout << "new program" << this;
|
||||||
|
zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Program::~Program() {
|
||||||
|
//piCout << "destroy program" << this;
|
||||||
|
if (context_)
|
||||||
|
context_->programs_.removeAll(this);
|
||||||
|
piForeach (Kernel * k, kernels_)
|
||||||
|
delete k;
|
||||||
|
if (PRIVATE->program)
|
||||||
|
clReleaseProgram(PRIVATE->program);
|
||||||
|
zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::Program::zero() {
|
||||||
|
context_ = 0;
|
||||||
|
kernels_.clear();
|
||||||
|
PRIVATE->program = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIOpenCL::Program::initKernels(PIVector<void * > kerns) {
|
||||||
|
piForeach (void * _k, kerns) {
|
||||||
|
cl_kernel k = (cl_kernel)_k;
|
||||||
|
//piCout << "init kernel" << k;
|
||||||
|
Kernel * kern = new Kernel();
|
||||||
|
kern->context_ = context_;
|
||||||
|
kern->program_ = this;
|
||||||
|
kern->PRIVATEWB->kernel = k;
|
||||||
|
if (kern->init())
|
||||||
|
kernels_ << kern;
|
||||||
|
else
|
||||||
|
delete kern;
|
||||||
|
}
|
||||||
|
return !kernels_.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Kernel::Kernel() {
|
||||||
|
zero();
|
||||||
|
//piCout << "new Kernel" << this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::Kernel::~Kernel() {
|
||||||
|
//piCout << "del Kernel" << this;
|
||||||
|
if (PRIVATE->kernel)
|
||||||
|
clReleaseKernel(PRIVATE->kernel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::Kernel::zero() {
|
||||||
|
PRIVATE->kernel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIOpenCL::Kernel::init() {
|
||||||
|
char kname[1024];
|
||||||
|
memset(kname, 0, 1024);
|
||||||
|
cl_int ret = 0;
|
||||||
|
ret = clGetKernelInfo(PRIVATE->kernel, CL_KERNEL_FUNCTION_NAME, 1024, kname, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelInfo(CL_KERNEL_FUNCTION_NAME) error" << ret;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name_ = kname;
|
||||||
|
cl_uint na = 0;
|
||||||
|
ret = clGetKernelInfo(PRIVATE->kernel, CL_KERNEL_NUM_ARGS, sizeof(na), &na, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelInfo(CL_KERNEL_NUM_ARGS) error" << ret;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (cl_uint i = 0; i < na; ++i) {
|
||||||
|
KernelArg ka;
|
||||||
|
ka.init(PRIVATE->kernel, i);
|
||||||
|
args_ << ka;
|
||||||
|
}
|
||||||
|
piCout << "kname" << kname << na;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIOpenCL::Kernel::setArgValueV(int index, const PIVariant & value) {
|
||||||
|
if (index < 0 || index >= args_.size_s()) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "setArgValue invalid index" << index;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIOpenCL::Kernel::argIndex(const PIString & an) const {
|
||||||
|
for (int i = 0; i < args_.size_s(); ++i)
|
||||||
|
if (args_[i].arg_name == an)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::KernelArg PIOpenCL::Kernel::argByName(const PIString & an) const {
|
||||||
|
piForeachC (KernelArg & a, args_)
|
||||||
|
if (a.arg_name == an)
|
||||||
|
return a;
|
||||||
|
return KernelArg();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PIOpenCL::KernelArg::KernelArg() {
|
||||||
|
address_qualifier = AddressGlobal;
|
||||||
|
access_qualifier = AccessNone;
|
||||||
|
type_qualifier = TypeNone;
|
||||||
|
is_pointer = false;
|
||||||
|
arg_type = Float;
|
||||||
|
dims = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIOpenCL::KernelArg::init(void * _k, uint index) {
|
||||||
|
cl_kernel k = (cl_kernel)_k;
|
||||||
|
cl_int ret = 0;
|
||||||
|
char nm[1024];
|
||||||
|
memset(nm, 0, 1024);
|
||||||
|
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_TYPE_NAME, 1024, nm, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelArgInfo(CL_KERNEL_ARG_TYPE_NAME) error" << ret;
|
||||||
|
}
|
||||||
|
type_name = nm;
|
||||||
|
memset(nm, 0, 1024);
|
||||||
|
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_NAME, 1024, nm, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelArgInfo(CL_KERNEL_ARG_NAME) error" << ret;
|
||||||
|
}
|
||||||
|
arg_name = nm;
|
||||||
|
cl_kernel_arg_address_qualifier addq = 0;
|
||||||
|
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof(addq), &addq, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelArgInfo(CL_KERNEL_ARG_ADDRESS_QUALIFIER) error" << ret;
|
||||||
|
}
|
||||||
|
switch (addq) {
|
||||||
|
case CL_KERNEL_ARG_ADDRESS_GLOBAL : address_qualifier = AddressGlobal; break;
|
||||||
|
case CL_KERNEL_ARG_ADDRESS_LOCAL : address_qualifier = AddressLocal; break;
|
||||||
|
case CL_KERNEL_ARG_ADDRESS_CONSTANT: address_qualifier = AddressConstant; break;
|
||||||
|
case CL_KERNEL_ARG_ADDRESS_PRIVATE : address_qualifier = AddressPrivate; break;
|
||||||
|
}
|
||||||
|
cl_kernel_arg_access_qualifier accq = 0;
|
||||||
|
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_ACCESS_QUALIFIER, sizeof(accq), &accq, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelArgInfo(CL_KERNEL_ARG_ACCESS_QUALIFIER) error" << ret;
|
||||||
|
}
|
||||||
|
switch (accq) {
|
||||||
|
case CL_KERNEL_ARG_ACCESS_READ_ONLY : access_qualifier = AccessReadOnly; break;
|
||||||
|
case CL_KERNEL_ARG_ACCESS_WRITE_ONLY: access_qualifier = AccessWriteOnly; break;
|
||||||
|
case CL_KERNEL_ARG_ACCESS_READ_WRITE: access_qualifier = AccessReadWrite; break;
|
||||||
|
case CL_KERNEL_ARG_ACCESS_NONE : access_qualifier = AccessNone; break;
|
||||||
|
}
|
||||||
|
cl_kernel_arg_type_qualifier tq = 0;
|
||||||
|
ret = clGetKernelArgInfo(k, index, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof(tq), &tq, 0);
|
||||||
|
if (ret != 0) {
|
||||||
|
piCout << "[PIOpenCL::Kernel]" << "clGetKernelArgInfo(CL_KERNEL_ARG_TYPE_QUALIFIER) error" << ret;
|
||||||
|
}
|
||||||
|
switch (tq) {
|
||||||
|
case CL_KERNEL_ARG_TYPE_CONST : type_qualifier = TypeConst; break;
|
||||||
|
case CL_KERNEL_ARG_TYPE_RESTRICT: type_qualifier = TypeRestrict; break;
|
||||||
|
case CL_KERNEL_ARG_TYPE_VOLATILE: type_qualifier = TypeVolatile; break;
|
||||||
|
case CL_KERNEL_ARG_TYPE_NONE : type_qualifier = TypeNone; break;
|
||||||
|
}
|
||||||
|
base_type_name = type_name;
|
||||||
|
is_pointer = false;
|
||||||
|
if (type_name.endsWith("*")) {
|
||||||
|
is_pointer = true;
|
||||||
|
base_type_name.cutRight(1);
|
||||||
|
}
|
||||||
|
dims = piMaxi(1, base_type_name.right(1).toInt());
|
||||||
|
if (dims > 1) base_type_name.cutRight(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PICout operator <<(PICout s, const PIOpenCL::KernelArg & v) {
|
||||||
|
s.setControl(0); s << "Arg(" << v.base_type_name << " " << v.arg_name << " (addr=" << v.address_qualifier << ",acc=" << v.access_qualifier << ",typ=" << v.type_qualifier << ",dims=" << v.dims << "))";
|
||||||
|
s.restoreControl(); return s;
|
||||||
|
}
|
||||||
2
src_opencl/resources.conf
Normal file
2
src_opencl/resources.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[PIOpenCL]
|
||||||
|
3rd/clcomplex.h
|
||||||
@@ -8,11 +8,12 @@ using namespace PICoutManipulators;
|
|||||||
void usage() {
|
void usage() {
|
||||||
piCout << Bold << "PIP Resources Compiler";
|
piCout << Bold << "PIP Resources Compiler";
|
||||||
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine;
|
||||||
piCout << Green << Bold << "Usage:" << Default << "\"pirc [-h] -i <in_file> -o <out_file>\"" << NewLine;
|
piCout << Green << Bold << "Usage:" << Default << "\"pirc [-hl] -i <in_file> -o <out_file>\"" << NewLine;
|
||||||
piCout << Green << Bold << "Details:";
|
piCout << Green << Bold << "Details:";
|
||||||
piCout << "-h --help " << Green << "- display this message and exit";
|
piCout << "-h --help " << Green << "- display this message and exit";
|
||||||
piCout << "-i --input <in_file> " << Green << "- resources description file";
|
piCout << "-i --input <in_file> " << Green << "- resources description file";
|
||||||
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
|
piCout << "-o --out <out_file> " << Green << "- output .cpp file";
|
||||||
|
piCout << "-l --list " << Green << "- print readed files from description and exit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -21,10 +22,10 @@ int main (int argc, char * argv[]) {
|
|||||||
cli.addArgument("input", true);
|
cli.addArgument("input", true);
|
||||||
cli.addArgument("out", true);
|
cli.addArgument("out", true);
|
||||||
cli.addArgument("help");
|
cli.addArgument("help");
|
||||||
|
cli.addArgument("list");
|
||||||
|
|
||||||
if (!cli.hasArgument("input") ||
|
if (cli.hasArgument("help") || !cli.hasArgument("input") ||
|
||||||
!cli.hasArgument("out") ||
|
(!cli.hasArgument("out") && !cli.hasArgument("list"))) {
|
||||||
cli.hasArgument("help")) {
|
|
||||||
usage();
|
usage();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -36,17 +37,21 @@ int main (int argc, char * argv[]) {
|
|||||||
piCout << "Error: resources description file is empty";
|
piCout << "Error: resources description file is empty";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*piForeachC (ParserSection & s, files) {
|
if (cli.hasArgument("list")) {
|
||||||
piCout << "[" << s.name << "]";
|
piForeachC (ParserSection & s, files) {
|
||||||
piCout << s.files;
|
piForeachC (ParserEntry & e, s.files) {
|
||||||
}*/
|
piCout << e.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
PIString out_file = cli.argumentValue("out");
|
PIString out_file = cli.argumentValue("out");
|
||||||
PIFile outf;
|
PIFile outf;
|
||||||
if (!out_file.isEmpty()) {
|
if (!out_file.isEmpty()) {
|
||||||
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
if (outf.open(out_file, PIIODevice::ReadWrite)) {
|
||||||
outf.clear();
|
outf.clear();
|
||||||
} else piCout << "Error: while open out file";
|
} else piCout << "Error: can`t open out file";
|
||||||
outf << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
outf << "// Generated by \"PIP Resources Compiler\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n");
|
||||||
outf << "// Execute command:\n";
|
outf << "// Execute command:\n";
|
||||||
piForeachC (PIString & _a, cli.rawArguments())
|
piForeachC (PIString & _a, cli.rawArguments())
|
||||||
|
|||||||
Reference in New Issue
Block a user