1 /*
2  *Copyright (c) 2018 Intel Corporation.
3  *
4  *Permission is hereby granted, free of charge, to any person obtaining a copy
5  *of this software and associated documentation files (the "Software"), to deal
6  *in the Software without restriction, including without limitation the rights
7  *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  *copies of the Software, and to permit persons to whom the Software is
9  *furnished to do so, subject to the following conditions:
10  *
11  *The above copyright notice and this permission notice shall be included in
12  *all copies or substantial portions of the Software.
13  *
14  *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  *THE SOFTWARE.
21  *
22  */
23 
24 
25 #include <stdio.h>
26 
27 #include "dl_compression.h"
28 #include "dl_compression_impl.hpp"
29 
30 
dl_comp_compress_buffer(const void * src,void * dst,size_t dataCount,void * diff,dl_comp_data_type_t src_data_type,size_t comp_ratio,dl_comp_method_t method)31 dl_comp_return_t dl_comp_compress_buffer( const void *src,
32                                           void *dst,
33                                           size_t dataCount,
34                                           void *diff,
35                                           dl_comp_data_type_t src_data_type,
36                                           size_t comp_ratio,
37                                           dl_comp_method_t method )
38 {
39     // Parameter checking
40     if (src_data_type != DL_COMP_FLOAT32) {
41         return DL_COMP_FAIL_SRC_DATA_TYPE_NOT_SUPPORTED;
42     }
43 
44     if (comp_ratio != 4) {
45         return DL_COMP_FAIL_RATIO_NOT_SUPPORTED;
46     }
47 
48     if (method != DL_COMP_DFP) {
49         return DL_COMP_FAIL_COMP_METHOD_NOT_SUPPORTED;
50     }
51 
52     // Do compession
53     DLCompressBase *compInst = DLCompressBase::get_compression_instance(DL_COMP_DFP);
54 
55     return compInst->compress_buffer((float *)src,
56                                      (int8_t *)dst,
57                                      (float *)diff,
58                                      dataCount,
59                                      src == dst);
60 }
61 
dl_comp_decompress_buffer(const void * src,void * dst,size_t dataCount)62 dl_comp_return_t dl_comp_decompress_buffer( const void *src,
63                                             void *dst,
64                                             size_t dataCount )
65 {
66     dl_comp_head *compHead = (dl_comp_head *)src;
67 
68     if (compHead->magic != DL_COMP_HEAD_MAGIC) {
69         // This is a work-around for MLSL. Because in MPI_Test
70         // sometimes an already de-compressed buffer may be sent
71         // to compress lib to do de-compressed buffer. So we
72         // simply ignore it in this case.
73         return DL_COMP_OK;
74     }
75 
76     size_t blockCount = dataCount % DL_COMP_BLOCK_NUM == 0 ? (dataCount / DL_COMP_BLOCK_NUM) : (dataCount / DL_COMP_BLOCK_NUM + 1);
77     // do de-compression
78     DLCompressBase *compInst = DLCompressBase::get_compression_instance(DL_COMP_DFP);
79 
80     return compInst->decompress_buffer((const int8_t *)src, (float *)dst, blockCount);
81 }
82 
dl_comp_compressed_buffer_sum(const void * inBuffer1,const void * inBuffer2,size_t dataCount,void * outBuffer)83 dl_comp_return_t dl_comp_compressed_buffer_sum( const void *inBuffer1,
84                                                 const void *inBuffer2,
85                                                 size_t dataCount,
86                                                 void *outBuffer )
87 {
88     return DL_COMP_FAIL_NOT_SUPPORTED;
89 }
90 
dl_comp_get_sizeof_block(dl_comp_data_type_t src_data_type,size_t comp_ratio,dl_comp_method_t method)91 size_t dl_comp_get_sizeof_block( dl_comp_data_type_t src_data_type,
92                                  size_t comp_ratio,
93                                  dl_comp_method_t method )
94 {
95     size_t blockSize = 0;
96     if (src_data_type == DL_COMP_FLOAT32 &&
97         comp_ratio == 4 &&
98         method == DL_COMP_DFP) {
99         blockSize = sizeof(int8_t) * DL_COMP_BLOCK_NUM + sizeof(dl_comp_head);
100     }
101 
102     return blockSize;
103 }
104 
dl_comp_get_elem_num_in_block()105 size_t dl_comp_get_elem_num_in_block()
106 {
107     return DL_COMP_BLOCK_NUM;
108 }
109 
dl_comp_compressed_buffer_reduce_sum(const void * inBuffer,void * inoutBuffer,size_t blockCount)110 dl_comp_return_t  dl_comp_compressed_buffer_reduce_sum( const void *inBuffer,
111                                                         void *inoutBuffer,
112                                                         size_t blockCount )
113 {
114     DLCompressBase *compInst = DLCompressBase::get_compression_instance(DL_COMP_DFP);
115 
116     return compInst->compress_sum2((const int8_t *)inBuffer, (int8_t *)inoutBuffer, blockCount);
117 }
118 
dl_comp_convert_block_count(size_t dataCount)119 size_t dl_comp_convert_block_count(size_t dataCount)
120 {
121     size_t blockCount = dataCount % DL_COMP_BLOCK_NUM == 0 ?
122                         (dataCount / DL_COMP_BLOCK_NUM) : (dataCount / DL_COMP_BLOCK_NUM + 1);
123     return blockCount;
124 }
125 
dl_comp_check_running_environ()126 bool dl_comp_check_running_environ()
127 {
128   // Currently, we only check whether avx512 instruction supported.
129   return dl_comp_check_avx512_supported();
130 }
131 
dl_comp_compress_buffer_FLOAT32ToINT8(const void * srcBuffer,void * dstBuffer,void * diff,size_t dataCount)132 int dl_comp_compress_buffer_FLOAT32ToINT8( const void *srcBuffer,
133                                             void *dstBuffer,
134                                             void *diff,
135                                             size_t dataCount)
136 {
137     DLCompressBase *compInst = DLCompressBase::get_compression_instance(DL_COMP_DFP);
138 
139     dl_comp_return_t ret =  compInst->compress_buffer((float *)srcBuffer,
140                                                       (int8_t *)dstBuffer,
141                                                       (float *)diff,
142                                                       dataCount,
143                                                       srcBuffer == dstBuffer);
144     return ret;
145 }
146 
dl_comp_decompress_buffer_INT8ToFLOAT32(const void * srcBuffer,void * dstBuffer,size_t dataCount)147 int dl_comp_decompress_buffer_INT8ToFLOAT32(const void *srcBuffer,
148                                             void *dstBuffer,
149                                             size_t dataCount)
150 {
151     dl_comp_head *compHead = (dl_comp_head *)srcBuffer;
152 
153     if (compHead->magic != DL_COMP_HEAD_MAGIC) {
154         // This is a work-around for MLSL. Because in MPI_Test
155         // sometimes an already de-compressed buffer may be sent
156         // to compress lib to do de-compressed buffer. So we
157         // simply ignore it in this case.
158         return DL_COMP_OK;
159     }
160 
161     // do de-compression
162     size_t blockCount = dataCount % DL_COMP_BLOCK_NUM == 0 ?
163                         (dataCount / DL_COMP_BLOCK_NUM) : (dataCount / DL_COMP_BLOCK_NUM + 1);
164     DLCompressBase *compInst = DLCompressBase::get_compression_instance(DL_COMP_DFP);
165     dl_comp_return_t ret = compInst->decompress_buffer((const int8_t *)srcBuffer, (float *)dstBuffer, blockCount);
166 
167     return ret;
168 }
169