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 #include <stdlib.h> // srand()
19 #include <string.h> // memcpy()
20 #include <gtest/gtest.h>
21 #include <clBLAS.h>
22 #include <common.h>
23 #include <blas-internal.h>
24 #include <blas-wrapper.h>
25 #include <clBLAS-wrapper.h>
26 #include <BlasBase.h>
27 #include <blas-random.h>
28 #include <iamax.h>
29
30 static void
releaseMemObjects(cl_mem objX,cl_mem objiAmax,cl_mem objScratch)31 releaseMemObjects(cl_mem objX, cl_mem objiAmax, cl_mem objScratch)
32 {
33 if(objX != NULL)
34 {
35 clReleaseMemObject(objX);
36 }
37 if(objiAmax != NULL)
38 {
39 clReleaseMemObject(objiAmax);
40 }
41 if(objScratch != NULL)
42 {
43 clReleaseMemObject(objScratch);
44 }
45 }
46
47 template <typename T> static void
deleteBuffers(T * blasX,int * blasiAmax=NULL,int * clblasiAmax=NULL)48 deleteBuffers(T *blasX, int *blasiAmax=NULL, int *clblasiAmax=NULL)
49 {
50 if(blasX != NULL)
51 {
52 delete[] blasX;
53 }
54 if(clblasiAmax != NULL)
55 {
56 delete[] clblasiAmax;
57 }
58 if(blasiAmax != NULL)
59 {
60 delete(blasiAmax);
61 }
62 }
63
64 template <typename T>
65 void
iamaxCorrectnessTest(TestParams * params)66 iamaxCorrectnessTest(TestParams *params)
67 {
68 cl_int err;
69 T *blasX;
70 int *clblasiAmax, *blasiAmax;
71 cl_mem bufX, bufiAmax, scratchBuff;
72 clMath::BlasBase *base;
73 cl_event *events;
74
75 base = clMath::BlasBase::getInstance();
76
77 if ((typeid(T) == typeid(cl_double) ||
78 typeid(T) == typeid(DoubleComplex)) &&
79 !base->isDevSupportDoublePrecision()) {
80
81 std::cerr << ">> WARNING: The target device doesn't support native "
82 "double precision floating point arithmetic" <<
83 std::endl << ">> Test skipped" << std::endl;
84 SUCCEED();
85 return;
86 }
87
88 printf("number of command queues : %d\n\n", params->numCommandQueues);
89
90 events = new cl_event[params->numCommandQueues];
91 memset(events, 0, params->numCommandQueues * sizeof(cl_event));
92
93 size_t lengthX = (1 + ((params->N -1) * abs(params->incx)));
94
95 blasX = new T[lengthX + params->offBX ];
96 blasiAmax = new int[1];
97 clblasiAmax = new int[1 + params->offa];
98
99 if((blasX == NULL) || (clblasiAmax == NULL) || (blasiAmax == NULL))
100 {
101 ::std::cerr << "Cannot allocate memory on host side\n" << "!!!!!!!!!!!!Test skipped.!!!!!!!!!!!!" << ::std::endl;
102 deleteBuffers<T>(blasX, blasiAmax, clblasiAmax);
103 delete[] events;
104 SUCCEED();
105 return;
106 }
107
108 srand(params->seed);
109 ::std::cerr << "Generating input data... ";
110
111 randomVectors<T>(params->N, (blasX + params->offBX), params->incx, NULL, 0);
112 ::std::cerr << "Done" << ::std::endl;
113
114 // Allocate buffers
115 bufX = base->createEnqueueBuffer(blasX, (lengthX + params->offBX)* sizeof(T), 0, CL_MEM_READ_ONLY);
116 bufiAmax = base->createEnqueueBuffer(NULL, (1 + params->offa) * sizeof(int), 0, CL_MEM_READ_WRITE);
117 scratchBuff = base->createEnqueueBuffer(NULL, (2 * lengthX * sizeof(T)), 0, CL_MEM_READ_WRITE);
118
119 ::std::cerr << "Calling reference xiAMAX routine... ";
120
121 *blasiAmax = ::clMath::blas::iamax( params->N, blasX, params->offBX, params->incx);
122 ::std::cerr << "Done" << ::std::endl;
123
124 if ((bufX == NULL) || (bufiAmax == NULL) || (scratchBuff == NULL)) {
125 releaseMemObjects(bufX, bufiAmax, scratchBuff);
126 deleteBuffers<T>(blasX, blasiAmax, clblasiAmax);
127 delete[] events;
128 ::std::cerr << ">> Failed to create/enqueue buffer for a matrix."
129 << ::std::endl
130 << ">> Can't execute the test, because data is not transfered to GPU."
131 << ::std::endl
132 << ">> Test skipped." << ::std::endl;
133 SUCCEED();
134 return;
135 }
136
137 ::std::cerr << "Calling clblas xiAMAX routine... ";
138
139 DataType type;
140 type = ( typeid(T) == typeid(cl_float))? TYPE_FLOAT : ( typeid(T) == typeid(cl_double))? TYPE_DOUBLE: ( typeid(T) == typeid(cl_float2))? TYPE_COMPLEX_FLOAT:TYPE_COMPLEX_DOUBLE;
141
142 // Should use bufXTemp as well
143 err = (cl_int)::clMath::clblas::iamax( type, params->N, bufiAmax, params->offa,
144 bufX, params->offBX, params->incx, scratchBuff,
145 params->numCommandQueues, base->commandQueues(), 0, NULL, events);
146
147 if (err != CL_SUCCESS) {
148 releaseMemObjects(bufX, bufiAmax, scratchBuff);
149 deleteBuffers<T>(blasX, blasiAmax, clblasiAmax);
150 delete[] events;
151 ASSERT_EQ(CL_SUCCESS, err) << "::clMath::clblas::iAMAX() failed";
152 }
153
154 err = waitForSuccessfulFinish(params->numCommandQueues,
155 base->commandQueues(), events);
156 if (err != CL_SUCCESS) {
157 releaseMemObjects(bufX, bufiAmax, scratchBuff);
158 deleteBuffers<T>(blasX, blasiAmax, clblasiAmax);
159 delete[] events;
160 ASSERT_EQ(CL_SUCCESS, err) << "waitForSuccessfulFinish()";
161 }
162 ::std::cerr << "Done" << ::std::endl;
163
164
165 err = clEnqueueReadBuffer(base->commandQueues()[0], bufiAmax, CL_TRUE, 0,
166 (1 + params->offa) * sizeof(*clblasiAmax), clblasiAmax, 0, NULL, NULL);
167 if (err != CL_SUCCESS)
168 {
169 ::std::cerr << "iAMAX: Reading results failed...." << std::endl;
170 }
171
172 compareValues<int>((blasiAmax), (clblasiAmax+params->offa), 0);
173 releaseMemObjects(bufX, bufiAmax, scratchBuff);
174 deleteBuffers<T>(blasX, blasiAmax, clblasiAmax);
175 delete[] events;
176 }
177
178 // Instantiate the test
179
TEST_P(iAMAX,isamax)180 TEST_P(iAMAX, isamax) {
181 TestParams params;
182
183 getParams(¶ms);
184 iamaxCorrectnessTest<cl_float>(¶ms);
185 }
186
TEST_P(iAMAX,idamax)187 TEST_P(iAMAX, idamax) {
188 TestParams params;
189
190 getParams(¶ms);
191 iamaxCorrectnessTest<cl_double>(¶ms);
192 }
193
TEST_P(iAMAX,icamax)194 TEST_P(iAMAX, icamax) {
195 TestParams params;
196
197 getParams(¶ms);
198 iamaxCorrectnessTest<FloatComplex>(¶ms);
199 }
200
TEST_P(iAMAX,izamax)201 TEST_P(iAMAX, izamax) {
202 TestParams params;
203
204 getParams(¶ms);
205 iamaxCorrectnessTest<DoubleComplex>(¶ms);
206 }
207