TTopK.cpp 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* NiuTrans.Tensor - an open-source tensor library
* Copyright (C) 2017, Natural Language Processing Lab, Northestern University.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
* $Created by: Xu Chen (email: hello_master1954@163.com) 2018-06-27
*/

#include "TTopK.h"

namespace nts { // namespace nts(NiuTrans.Tensor)
liyinqiao committed
25 26 27 28 29 30

/* 
case 1: get the top-k items along a given dimension.
In this case, 
(2, 4) -> (2, 4), dim = 0, k = 2
(2, 4) -> (2, 4), dim = 1, k = 4
liyinqiao committed
31
*/
32 33
bool TestTopK1()
{
liyinqiao committed
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
    /* a input tensor of size (2, 4) */
    int sOrder = 2;
    int * sDimSize = new int[sOrder];
    sDimSize[0] = 2;
    sDimSize[1] = 4;

    int sUnitNum = 1;
    for (int i = 0; i < sOrder; i++)
        sUnitNum *= sDimSize[i];

    /* a output tensor of size (2, 4) */
    int tOrder = 2;
    int * tDimSize = new int[tOrder];
    tDimSize[0] = 2;
    tDimSize[1] = 4;

    int tUnitNum = 1;
    for (int i = 0; i < tOrder; i++)
        tUnitNum *= tDimSize[i];

liyinqiao committed
54 55
    DTYPE sData[2][4] = { {5.0F, 1.0F, 2.0F, 8.0F},
                          {4.0F, 3.0F, 7.0F, 6.0F} };
liyinqiao committed
56

liyinqiao committed
57 58
    DTYPE tAnswer1[2][4] = { {5.0F, 3.0F, 7.0F, 8.0F},
                             {4.0F, 1.0F, 2.0F, 6.0F} };
liyinqiao committed
59 60 61
    int indexAnswer1[2][4] = { {0, 1, 1, 0},
                               {1, 0, 0, 1} };

liyinqiao committed
62 63
    DTYPE tAnswer2[2][4] = { {8.0F, 5.0F, 2.0F, 1.0F},
                             {7.0F, 6.0F, 4.0F, 3.0F} };
liyinqiao committed
64
    int indexAnswer2[2][4] = { {3, 0, 2, 1},
65 66 67 68 69 70
                               {2, 3, 0, 1} };

    /* CPU test */
    bool cpuTest = true;

    /* create tensors */
liyinqiao committed
71 72 73 74 75
    XTensor * s = NewTensor(sOrder, sDimSize);
    XTensor * t1 = NewTensor(tOrder, tDimSize);
    XTensor * t2 = NewTensor(tOrder, tDimSize);
    XTensor * index1 = NewTensor(tOrder, tDimSize, X_INT);
    XTensor * index2 = NewTensor(tOrder, tDimSize, X_INT);
76

77 78 79 80 81 82
    XTensor sUser = XTensor(sOrder, sDimSize, X_FLOAT, 1.0F, -1, NULL);
    XTensor tUser1 = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, -1, NULL);
    XTensor tUser2 = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, -1, NULL);
    XTensor indexUser1 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, -1, NULL);
    XTensor indexUser2 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, -1, NULL);

83
    /* initialize variables */
liyinqiao committed
84 85 86 87 88
    s->SetData(sData, sUnitNum);
    t1->SetZeroAll();
    t2->SetZeroAll();
    index1->SetZeroAll();
    index2->SetZeroAll();
89

90 91 92 93 94 95
    sUser.SetData(sData, sUnitNum);
    tUser1.SetZeroAll();
    tUser2.SetZeroAll();
    indexUser1.SetZeroAll();
    indexUser2.SetZeroAll();

96 97
    /* call TopK function */
    int dim = 0;
liyinqiao committed
98
    int k = sDimSize[dim];
99
    _TopK(s, t1, index1, dim, k);
100
    TopK(sUser, tUser1, indexUser1, dim, k);
101 102

    dim = 1;
liyinqiao committed
103
    k = sDimSize[dim];
104
    _TopK(s, t2, index2, dim, k);
105
    TopK(sUser, tUser2, indexUser2, dim, k);
106 107

    /* check results */
108 109 110 111
    cpuTest = t1->CheckData(tAnswer1, tUnitNum) && tUser1.CheckData(tAnswer1, tUnitNum)
           && t2->CheckData(tAnswer2, tUnitNum) && tUser2.CheckData(tAnswer2, tUnitNum)
           && index1->CheckData(indexAnswer1, tUnitNum) && indexUser1.CheckData(indexAnswer1, tUnitNum)
           && index2->CheckData(indexAnswer2, tUnitNum) && indexUser2.CheckData(indexAnswer2, tUnitNum);
112 113 114 115 116 117

#ifdef USE_CUDA
    /* GPU test */
    bool gpuTest = true;

    /* create tensors */
liyinqiao committed
118 119 120 121 122
    XTensor * sGPU = NewTensor(sOrder, sDimSize, X_FLOAT, 1.0F, 0);
    XTensor * tGPU1 = NewTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0);
    XTensor * tGPU2 = NewTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0);
    XTensor * indexGPU1 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0);
    XTensor * indexGPU2 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0);
123
    
124 125 126 127 128 129
    XTensor sUserGPU = XTensor(sOrder, sDimSize, X_FLOAT, 1.0F, 0, NULL);
    XTensor tUserGPU1 = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0, NULL);
    XTensor tUserGPU2 = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0, NULL);
    XTensor indexUserGPU1 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0, NULL);
    XTensor indexUserGPU2 = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0, NULL);

130
    /* initialize variables */
liyinqiao committed
131 132 133 134 135
    sGPU->SetData(sData, sUnitNum);
    tGPU1->SetZeroAll();
    tGPU2->SetZeroAll();
    indexGPU1->SetZeroAll();
    indexGPU2->SetZeroAll();
136

137 138 139 140 141 142
    sUserGPU.SetData(sData, sUnitNum);
    tUserGPU1.SetZeroAll();
    tUserGPU2.SetZeroAll();
    indexUserGPU1.SetZeroAll();
    indexUserGPU2.SetZeroAll();

143 144
    /* call TopK function */
    dim = 0;
liyinqiao committed
145
    k = sDimSize[dim];
146
    _TopK(sGPU, tGPU1, indexGPU1, dim, k);
147
    TopK(sUserGPU, tUserGPU1, indexUserGPU1, dim, k);
148 149
    
    dim = 1;
liyinqiao committed
150
    k = sDimSize[dim];
151
    _TopK(sGPU, tGPU2, indexGPU2, dim, k);
152
    TopK(sUserGPU, tUserGPU2, indexUserGPU2, dim, k);
153 154
    
    /* check results */
155 156 157 158
    gpuTest = tGPU1->CheckData(tAnswer1, tUnitNum) && tUserGPU1.CheckData(tAnswer1, tUnitNum)
              && tGPU2->CheckData(tAnswer2, tUnitNum) && tUserGPU2.CheckData(tAnswer2, tUnitNum)
              && indexGPU1->CheckData(indexAnswer1, tUnitNum) && indexUserGPU1.CheckData(indexAnswer1, tUnitNum)
              && indexGPU2->CheckData(indexAnswer2, tUnitNum) && indexUserGPU2.CheckData(indexAnswer2, tUnitNum);
159 160

    /* destroy variables */
liyinqiao committed
161 162 163 164 165 166 167 168 169 170 171 172
    delete s;
    delete t1;
    delete t2;
    delete index1;
    delete index2;
    delete sGPU;
    delete tGPU1;
    delete tGPU2;
    delete indexGPU1;
    delete indexGPU2;
    delete[] sDimSize;
    delete[] tDimSize;
173 174 175 176

    return cpuTest && gpuTest;
#else
    /* destroy variables */
liyinqiao committed
177 178 179 180 181 182 183 184 185 186 187 188
    delete s;
    delete t1;
    delete t2;
    delete index1;
    delete index2;
    delete[] sDimSize;
    delete[] tDimSize;

    return cpuTest;
#endif // USE_CUDA
}

liyinqiao committed
189 190 191
/*
case 2: get the top-k items along a given dimension.
In this case, (2, 4) -> (2, 2), dim = 1, k = 2.
liyinqiao committed
192 193 194 195 196 197 198 199
*/
bool TestTopK2()
{
    /* a input tensor of size (2, 4) */
    int sOrder = 2;
    int * sDimSize = new int[sOrder];
    sDimSize[0] = 2;
    sDimSize[1] = 4;
200

liyinqiao committed
201 202 203 204 205 206 207 208 209 210 211 212 213 214
    int sUnitNum = 1;
    for (int i = 0; i < sOrder; i++)
        sUnitNum *= sDimSize[i];

    /* a output tensor of size (2, 2) */
    int tOrder = 2;
    int * tDimSize = new int[tOrder];
    tDimSize[0] = 2;
    tDimSize[1] = 2;

    int tUnitNum = 1;
    for (int i = 0; i < tOrder; i++)
        tUnitNum *= tDimSize[i];

liyinqiao committed
215 216 217 218
    DTYPE sData[2][4] = { {5.0F, 1.0F, 2.0F, 8.0F},
                          {4.0F, 3.0F, 7.0F, 6.0F} };
    DTYPE tAnswer[2][2] = { {8.0F, 5.0F},
                            {7.0F, 6.0F} };
liyinqiao committed
219 220 221 222 223 224 225 226 227 228
    int indexAnswer[2][2] = { {3, 0},
                              {2, 3} };

    /* CPU test */
    bool cpuTest = true;

    /* create tensors */
    XTensor * s = NewTensor(sOrder, sDimSize);
    XTensor * t = NewTensor(tOrder, tDimSize);
    XTensor * index = NewTensor(tOrder, tDimSize, X_INT);
229 230 231 232
    
    XTensor sUser = XTensor(sOrder, sDimSize, X_FLOAT, 1.0F, -1, NULL);
    XTensor tUser = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, -1, NULL);
    XTensor indexUser = NewTensor(tOrder, tDimSize, X_INT, 1.0F, -1, NULL);
liyinqiao committed
233 234 235 236 237 238

    /* initialize variables */
    s->SetData(sData, sUnitNum);
    t->SetZeroAll();
    index->SetZeroAll();

239 240 241 242
    sUser.SetData(sData, sUnitNum);
    tUser.SetZeroAll();
    indexUser.SetZeroAll();

liyinqiao committed
243 244 245
    /* call TopK function */
    int dim = 1;
    int k = tDimSize[dim];
246
    _TopK(s, t, index, dim, k);
247
    TopK(sUser, tUser, indexUser, dim, k);
liyinqiao committed
248 249

    /* check results */
250 251
    cpuTest = t->CheckData(tAnswer, tUnitNum) && tUser.CheckData(tAnswer, tUnitNum)
              && index->CheckData(indexAnswer, tUnitNum) && indexUser.CheckData(indexAnswer, tUnitNum);
liyinqiao committed
252 253 254 255 256 257 258 259 260 261

#ifdef USE_CUDA
    /* GPU test */
    bool gpuTest = true;

    /* create tensors */
    XTensor * sGPU = NewTensor(sOrder, sDimSize, X_FLOAT, 1.0F, 0);
    XTensor * tGPU = NewTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0);
    XTensor * indexGPU = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0);
    
262 263 264 265
    XTensor sUserGPU = XTensor(sOrder, sDimSize, X_FLOAT, 1.0F, 0, NULL);
    XTensor tUserGPU = XTensor(tOrder, tDimSize, X_FLOAT, 1.0F, 0, NULL);
    XTensor indexUserGPU = NewTensor(tOrder, tDimSize, X_INT, 1.0F, 0, NULL);

liyinqiao committed
266 267 268 269 270
    /* initialize variables */
    sGPU->SetData(sData, sUnitNum);
    tGPU->SetZeroAll();
    indexGPU->SetZeroAll();

271 272 273 274
    sUserGPU.SetData(sData, sUnitNum);
    tUserGPU.SetZeroAll();
    indexUserGPU.SetZeroAll();

liyinqiao committed
275 276 277
    /* call TopK function */
    dim = 1;
    k = tDimSize[dim];
278
    _TopK(sGPU, tGPU, indexGPU, dim, k);
279
    TopK(sUserGPU, tUserGPU, indexUserGPU, dim, k);
liyinqiao committed
280 281

    /* check results */
282 283 284
    gpuTest = tGPU->CheckData(tAnswer, tUnitNum) && tUserGPU.CheckData(tAnswer, tUnitNum)
              && indexGPU->CheckData(indexAnswer, tUnitNum) && indexUserGPU.CheckData(indexAnswer, tUnitNum);

liyinqiao committed
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    /* destroy variables */
    delete s;
    delete t;
    delete index;
    delete sGPU;
    delete tGPU;
    delete indexGPU;
    delete[] sDimSize;
    delete[] tDimSize;

    return cpuTest && gpuTest;
#else
    /* destroy variables */
    delete s;
    delete t;
    delete index;
    delete[] sDimSize;
    delete[] tDimSize;
303 304 305 306 307 308 309 310 311 312 313 314 315

    return cpuTest;
#endif // USE_CUDA
}

/* other cases */
/*
TODO!!
*/

/* test for TopK Function */
bool TestTopK()
{
liyinqiao committed
316
    XPRINT(0, stdout, "[TEST TopK] get the top-k items along a given dimension\n");
317
    bool returnFlag = true, caseFlag = true;
liyinqiao committed
318
    
319 320 321 322 323 324 325 326
    /* case 1 test */
    caseFlag = TestTopK1();
    if (!caseFlag) {
        returnFlag = false;
        XPRINT(0, stdout, ">> case 1 failed!\n");
    }
    else
        XPRINT(0, stdout, ">> case 1 passed!\n");
liyinqiao committed
327 328 329 330 331 332 333 334 335
    
    /* case 2 test */
    caseFlag = TestTopK2();
    if (!caseFlag) {
        returnFlag = false;
        XPRINT(0, stdout, ">> case 2 failed!\n");
    }
    else
        XPRINT(0, stdout, ">> case 2 passed!\n");
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

    /* other cases test */
    /*
    TODO!!
    */

    if (returnFlag) {
        XPRINT(0, stdout, ">> All Passed!\n");
    }
    else
        XPRINT(0, stdout, ">> Failed!\n");

    XPRINT(0, stdout, "\n");

    return returnFlag;
    }

} // namespace nts(NiuTrans.Tensor)