1 /* ************************************************************************
2  * Copyright 2013 Advanced Micro Devices, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  * ************************************************************************/
16 
17 
18 #ifndef BLASBASE_H_
19 #define BLASBASE_H_
20 
21 #include <clBLAS.h>
22 #include <common.h>
23 #include <algorithm>
24 
25 #if _MSC_VER
26 #pragma warning (disable:4127)
27 #endif
28 
29 // check it is double precision error and return
30 #define CHECK_DP_ERROR_AND_RETURN(err, funcName)                            \
31 do {                                                                        \
32     clMath::BlasBase *base = clMath::BlasBase::getInstance();                     \
33                                                                             \
34     if (err == CL_INVALID_DEVICE && !base->isDevSupportDoublePrecision()) { \
35         ::std::cerr << std::endl << ">> " << funcName <<                    \
36                 "() reported that this device doesn't support double "      \
37                 "precision floating point arithmetic. Test is skipped" <<   \
38         ::std::endl;                                                        \
39         SUCCEED();                                                          \
40                                                                             \
41         return;                                                             \
42     }                                                                       \
43 } while (0)                                                                 \
44 
45 #define DEFAULT_SEED 12345
46 #define MAX_COMMAND_QUEUES 10
47 
48 namespace clMath {
49 
50 // This class is a singleton
51 
52 class BlasBase {
53 private:
54     cl_platform_id platform_;
55     // used in all cases
56     cl_device_id primaryDevice_;
57     /*
58      * used only  in cases with MultipleQueues to cover problem distribution
59      * among different devices, not only different queues belonging to the same
60      * device
61      */
62     cl_device_id additionalDevice_;
63     cl_context context_;
64     cl_command_queue commandQueues_[MAX_COMMAND_QUEUES];
65 
66     bool useNumCommandQueues_;
67     cl_uint numCommandQueues_;
68 
69     bool useAlpha_;
70     bool useBeta_;
71     ComplexLong alpha_;
72     ComplexLong beta_;
73 
74     bool useSeed_;
75     unsigned int seed_;
76 
77     bool useM_, useN_, useK_;
78     size_t M_, N_, K_;
79 
80     bool useIncX_, useIncY_;
81     int incX_, incY_;
82 
83     bool useImages_;
84     cl_device_type devType_;
85     const char* devName_;
86     cl_ulong imageA_;
87     cl_ulong imageB_;
88 
89     BlasBase();
90     ~BlasBase();
91     BlasBase(const BlasBase &);             // intentionally undefined
92     BlasBase & operator=(const BlasBase &); // intentionally undefined
93 
94     void SetUp();
95     void TearDown();
96     bool initialized();
97 
98     cl_int getPlatforms(cl_platform_id** platforms, cl_int *error);
99     cl_device_id getDevice(cl_device_type type, const char* name,
100         cl_int *error);
101     void printDevInfoStr(cl_device_info param, const char *paramName,
102                          int primAdd);
103 
104 public:
105     static BlasBase* getInstance();
106 
context()107     cl_context context()
108     {
109         return context_;
110     };
111 
commandQueues()112     cl_command_queue* commandQueues() const
113     {
114         return const_cast<cl_command_queue*>(commandQueues_);
115     };
116 
useNumCommandQueues()117     bool useNumCommandQueues() const    { return useNumCommandQueues_; };
numCommandQueues()118     cl_uint numCommandQueues() const    { return numCommandQueues_; };
setNumCommandQueues(cl_uint numCommandQueues)119     void setNumCommandQueues(cl_uint numCommandQueues)
120     {
121         if (numCommandQueues <= MAX_COMMAND_QUEUES) {
122             numCommandQueues_ = numCommandQueues;
123             useNumCommandQueues_ = true;
124         }
125     }
126 
useAlpha()127     bool useAlpha() const        { return useAlpha_; }
alpha()128     ComplexLong alpha() const   { return alpha_; }
setAlpha(ComplexLong alpha)129     void setAlpha(ComplexLong alpha)
130     {
131         alpha_ = alpha;
132         useAlpha_ = true;
133     }
134 
useBeta()135     bool useBeta() const         { return useBeta_; }
beta()136     ComplexLong beta() const    { return beta_; }
setBeta(ComplexLong beta)137     void setBeta(ComplexLong beta)
138     {
139         beta_ = beta;
140         useBeta_ = true;
141     }
142 
useSeed()143     bool useSeed() const        { return useSeed_; };
seed()144     unsigned int seed() const   { return seed_; };
setSeed(unsigned int seed)145     void setSeed(unsigned int seed)
146     {
147         seed_ = seed;
148         useSeed_ = true;
149     }
150 
useM()151     bool useM() const           { return useM_; };
M()152     size_t M() const            { return M_; }
setM(size_t M)153     void setM(size_t M)
154     {
155         M_ = M;
156         useM_ = true;
157     }
158 
useN()159     bool useN() const           { return useN_; };
N()160     size_t N() const            { return N_; }
setN(size_t N)161     void setN(size_t N)
162     {
163         N_ = N;
164         useN_ = true;
165     }
166 
useK()167     bool useK() const           { return useK_; };
K()168     size_t K() const            { return K_; }
setK(size_t K)169     void setK(size_t K)
170     {
171         K_ = K;
172         useK_ = true;
173     }
174 
useIncX()175     bool useIncX() const        { return useIncX_; };
incX()176     int incX() const            { return incX_; }
setIncX(int incX)177     void setIncX(int incX)
178     {
179         incX_ = incX;
180         useIncX_ = true;
181     }
182 
useIncY()183     bool useIncY() const        { return useIncY_; };
incY()184     int incY() const            { return incY_; }
setIncY(int incY)185     void setIncY(int incY)
186     {
187         incY_ = incY;
188         useIncY_ = true;
189     }
190 
useImages()191     bool useImages() const      { return useImages_; };
setUseImages(bool value)192     void setUseImages(bool value)
193     {
194         useImages_ = value;
195     }
setUseImages(int value)196     void setUseImages(int value)
197     {
198         useImages_ = (value != 0);
199     }
200 
201     bool setDeviceType(cl_device_type* devType, const char* devName);
202     cl_mem createEnqueueBuffer(const void *data, size_t matrSize, size_t off,
203                                cl_mem_flags mode);
204     cl_mem readBuffer(void *ptr, size_t off, size_t size);
205 
206     clblasStatus addScratchImages(void);
207     void removeScratchImages(void);
208     size_t scratchImageWidth(void);
209     size_t scratchImageHeight(void);
210 
211     cl_ulong maxMemAllocSize(void);
212     cl_ulong availGlobalMemSize(int primAdd);
213 
214     bool isDevSupportDoublePrecision(void);
215     // print information on environment the test run in
216     void printEnvInfo(void);
217 
release(void)218     void release(void)
219     {
220         TearDown();
221     }
222 };
223 
224 }   // namespace
225 
226 #endif  // BLASBASE_H_
227