Initial public release.
[OpenCLIPER] / include / OpenCLIPER / NDArray.hpp
1 /* Copyright (C) 2018 Federico Simmross Wattenberg,
2  *                    Manuel Rodríguez Cayetano,
3  *                    Javier Royuela del Val,
4  *                    Elena Martín González,
5  *                    Elisa Moya Sáez,
6  *                    Marcos Martín Fernández and
7  *                    Carlos Alberola López
8  *
9  * This file is part of OpenCLIPER.
10  *
11  * OpenCLIPER is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; version 3 of the License.
14  *
15  * OpenCLIPER is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with OpenCLIPER; If not, see <http://www.gnu.org/licenses/>.
22  *
23  *
24  *  Contact:
25  *
26  *  Federico Simmross Wattenberg
27  *  E.T.S.I. Telecomunicación
28  *  Universidad de Valladolid
29  *  Paseo de Belén 15
30  *  47011 Valladolid, Spain.
31  *  fedsim@tel.uva.es
32  */
33 // Avoiding compiler errors due to multiple include of header files
34 #ifndef INCLUDE_OPENCLIPER_NDARRAY_HPP_
35 #define INCLUDE_OPENCLIPER_NDARRAY_HPP_
36
37 #include <memory>
38 #include <cstddef>
39 #include <iostream>
40 #include <OpenCLIPER/OpenCLIPERDataModelCommonDefs.hpp>
41 #include <LPISupport/Utils.hpp>
42 #include <OpenCLIPER/CLapp.hpp>
43 #include <typeinfo>
44 #include <OpenCLIPER/MatVarInfo.hpp>
45
46 namespace OpenCLIPER {
47 /// @brief class NDArray - n-dimensional matrix of data (abstract class, data type of data elements
48 /// is specific of subclasses).
49 class NDArray {
50     // Needed for accessing fields with write permission (get methods are read-only)
51     /// see @ref Data
52     friend class Data;
53     /// see @ref XData
54     friend class XData;
55     /// see @ref KData
56     friend class KData;
57
58 public:
59     /// Enum with keys for matlabStrides map.
60     enum matlabStridesKeys {
61         /// key for the stride between two consecutive data elements (number of stored real element values between them: 
62         /// 2 for data elements of complex type, 1 otherwise)
63         dataElement,
64         /// key for the stride between consecutive columns (number of stored real element values between them)
65         column, 
66         /// key for the stride between consecutive rows (number of stored real element values between them)
67         row, 
68         /// key for the stride between consecutive slices (number of stored real element values between them)
69         sliceAndBeyond};
70
71     NDArray();
72     virtual ~NDArray();
73
74     // Getters
75     /**
76     * @brief Gets pointer to data stored in device memory as a buffer
77     * (pointer to object of class cl::Buffer).
78     * @return raw pointer to object of class cl::Buffer
79     */
80     cl::Buffer* getDeviceBuffer() const {
81         return pDeviceBuffer;
82     }
83
84     /**
85     * @brief Gets pointer to data stored in device memory as a image
86     * (pointer to object of class cl::Image).
87     * @return raw pointer to object of class cl::Image
88     */
89     cl::Image* getDeviceImage() const {
90         return pDeviceImage;
91     }
92
93     /**
94     * @brief Gets pointer to data stored in host memory as a buffer
95     * (pointer to object of class cl::Buffer).
96     * @return raw pointer to object of class cl::Buffer
97     */
98     void* getHostBuffer() const {
99         return pHostBuffer;
100     }
101
102     /**
103     * @brief Gets pointer to data stored in host memory as a image
104     * (pointer to object of class cl::Image).
105     * @return raw pointer to object of class cl::Image
106     */
107     void* getHostImage() const {
108         return pHostImage;
109     }
110
111     const numberOfDimensionsType getNDims() const;
112
113     /**
114     * @brief Gets vector with dimensions of stored data (vector size is number of dimensions).
115     * @return vector with dimensions of stored data
116     */
117     const vector<dimIndexType>* getDims() const {
118         return (pDims.get());
119     }
120
121     const index1DType size() const;
122
123     // Setters
124     const std::string hostDataToString(std::string title) const;
125     const std::string hostImageToString(std::string title) const;
126     const std::string hostBufferToString(std::string title) const;
127     const std::string dimsToString(std::string title) const;
128     static dimIndexType getElementSize(ElementDataType elementDataType);
129     static NDArray* createNDArray(const string completeFileName, vector<dimIndexType>*& pTempDims, ElementDataType elementDataType);
130     static NDArray* createNDArray(const NDArray* pSourceData, bool copyData, ElementDataType elementDataType);
131     static NDArray* createNDArray(matvar_t *matvar, dimIndexType numOfSpatialDims, dimIndexType nDArrayOffsetInElements);
132     static NDArray* createNDArray(vector<dimIndexType>*& pSpatialDims, ElementDataType elementDataType);
133     template<typename T>
134     static NDArray* createNDArray(vector<dimIndexType>*& pSpatialDims, std::vector<T>*& pData);
135 protected:
136     /**
137      * @brief Calculates strides for accesing the NDArray as a contigouos memory data (using NDArray spatial dimensions).
138      */
139     virtual vector<dimIndexType>* calcUnaligned1DArrayStridesFromNDArrayDims() const = 0;
140
141     /**
142     * @brief Gets pointer to data stored in host memory (vector of elements) as a void pointer.
143     * @return raw pointer to data stored in host memory
144     */
145     virtual const void* getHostDataAsVoidPointer() const = 0;
146
147     /**
148     * @brief Sets pDeviceBuffer field. Uses move semantics, parameter value will be nullptr after executing this method.
149     * @param[in,out] pDeviceBuffer reference to pointer to device memory storing an OpenCL buffer
150     */
151     void setDeviceBuffer(cl::Buffer*& pDeviceBuffer) {
152         this->pDeviceBuffer = pDeviceBuffer;
153         pDeviceBuffer = nullptr;
154     }
155
156     /**
157     * @brief Sets pDeviceImage field. Uses move semantics, parameter value will be nullptr after executing this method.
158     * @param[in,out] pDeviceImage reference to pointer to device memory storing an OpenCL image
159     */
160     void setDeviceImage(cl::Image*& pDeviceImage) {
161         this->pDeviceImage = pDeviceImage;
162         pDeviceImage = nullptr;
163     }
164
165     /**
166     * @brief Sets pHostBuffer field. Uses move semantics, parameter value will be nullptr after executing this method.
167     * @param[in,out] pHostBuffer reference to void pointer to host memory with data stored as OpenCL buffer
168     */
169     void setHostBuffer(void*& pHostBuffer) {
170         this->pHostBuffer = pHostBuffer;
171         pHostBuffer = nullptr;
172     }
173
174     /**
175     * @brief Sets pHostImage field. Uses move semantics, parameter value will be nullptr after executing this method.
176     * @param[in,out] pHostImage reference to pointer to host memory with data stored as OpenCL image
177     */
178     void setHostImage(void*& pHostImage) {
179         this->pHostImage = pHostImage;
180         pHostImage = nullptr;
181     }
182
183     /**
184     * @brief Sets pDims (spatial dimensions) field. Use move semantics, parameter value will be nullptr after executing this method.
185     * @param[in,out] pDims reference to pointer to new vector with data spatial dimensions
186     */
187     void setDims(vector<dimIndexType>*& pDims) {
188         this->pDims.reset(pDims);
189         pDims = nullptr;
190     }
191
192     /**
193      * @brief Get matlab stride by key from matlabStrides field (strides are used for accessing elements inside matlab array).
194      * @param[in] key key of the stride to be got
195      * @return stride corresponding to the key parameter value
196      */
197     dimIndexType getMatlabStride(matlabStridesKeys key) {
198         return matlabStrides[key];
199     }
200
201     /**
202      * @brief Loads a data element from a matlab variable (previously read from a matlab file).
203      * @param[in] matvar matlab variable
204      * @param[in] offset offset to start reading from
205      */
206     virtual void loadMatlabHostDataElement(matvar_t* matvar, dimIndexType offset) = 0;
207
208     void loadMatlabHostData(matvar_t *matvar, dimIndexType numOfSpatialDims, dimIndexType nDArrayOffsetInElements);
209     static MatVarInfo* newMatVarInfo(ElementDataType elementDataType, dimIndexType numOfElements);
210     /**
211      * @brief Stores an element of a host memory array into a matlab array
212      * 
213      * @param[in] pMatVarInfo pointer to MatVarInfo object containing matlab data and dimensions
214      * @param[in] matlabElementOffset matlab variable offset to start writing to
215      * @param[in] nDArrayElementOffset NDArray host array offset to start reading from
216      * @param[in] syncSource type of data source: image (SyncSource::IMAGE_ONLY value) or buffer (SyncSource::BUFFER_ONLY value)
217      */
218     virtual void dumpMatlabElement(MatVarInfo* pMatVarInfo, dimIndexType matlabElementOffset, 
219                                                      dimIndexType nDArrayElementOffset, SyncSource syncSource) = 0;
220     void fillMatlabVarInfo(MatVarInfo* pMatVarInfo, const dimIndexType* pDimsInfo, const dimIndexType* pStridesInfo, dimIndexType nDArrayOffsetInElements, SyncSource syncSource);
221
222     // Must be set to pHostData->data value from setData method of ConcreteNDArray (so they must have protected visibility)
223     /** @brief buffer in host memory mapped from buffer in device memory. */
224     void* pHostBuffer = nullptr;
225
226     /** @brief image in host memory mapped from image in device memory. */
227     void* pHostImage = nullptr;
228
229 private:
230     const std::string hostImageOrBufferToString(std::string title, SyncSource syncSource) const;
231     const std::string nDArrayElementsToString(std::string title, const void* pArrayElements) const;
232     /**
233     * @brief Pure virtual method that converts one element of an array of data to a text representation (representation depends on the data type of 
234     * base element so this method must be defined in NDArray subclasses).
235     * @param[in] pElementsArray pointer to array of elements
236     * @param[in] index1D 1-dimensional index for element from array
237     * @return string with text representation of data element
238     */
239     virtual const std::string elementToString(const void *pElementsArray, dimIndexType index1D) const = 0;
240
241     // Attributes
242
243     /** @brief data in device memory (CPU/GPU) as a cl::Buffer type. */
244     cl::Buffer* pDeviceBuffer = nullptr;
245
246     /** @brief data in device memory (CPU/GPU) as a cl::Image type. */
247     cl::Image* pDeviceImage = nullptr;
248
249     /** @brief vector with the size of each data spatial dimension. */
250     std::unique_ptr<vector<dimIndexType>> pDims = nullptr;
251
252     /** @brief Map of strides for accessing matlab variables with 1D, 2D or 3D data. */
253     std::map<matlabStridesKeys,dimIndexType> matlabStrides;
254 };
255 }
256 #endif