CopyIndexed.cpp 5.36 KB
Newer Older
xiaotong committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/* 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: XIAO Tong (email: xiaotong@mail.neu.edu.cn) 2018-04-24
*/

#include "CopyIndexed.h"
#include "CopyBlocks.h"
24
#include "../../XName.h"
xiaotong committed
25 26 27 28 29

namespace nts { // namespace nts(NiuTrans.Tensor)

/*
copy indexed sub-tensors
30

xiaotong committed
31 32 33
>> s - the source tensor
>> t - the target tensor
>> dim - the leading dimension to define "sub-tensors"
34 35
         e.g., for a tensor of size (3, 2, 4) and dim = 2, 
         we have 4 sub-tensors of size (3,2)
xiaotong committed
36 37 38
>> srcIndex - index of the source sub-tensors
>> indexSize - length of srcIndex (and tgtIndex)
>> tgtIndex - index of the target sub-tensors
39
>> copyNum - number of the sub-tensors we copy for each source index, 
xiaotong committed
40 41
             e.g., for srcIndex = [1,4] and copyNum = 2,
             we actually copy the source sub-tensors 1, 2, 4, 5
xiaotong committed
42
*/
43
void _CopyIndexed(const XTensor * s, XTensor * t, int dim, int * srcIndex, int indexSize, int * tgtIndex, int copyNum)
xiaotong committed
44 45 46
{
    CheckNTErrors((s && t), "Invalid tensors!");
    CheckNTErrors((s->devID == t->devID || (s->devID < 0 && t->devID < 0)),
47
                  "the data must be kept on the same device!");
xiaotong committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
    CheckNTErrors((dim < s->order && dim < t->order), "A too larget dimension specified!");
    CheckNTErrors((s->unitSize == t->unitSize), "Unmatched tensors!");

    int dimRDI = s->order - dim - 1;
    int blockSizeSrc = 1;
    int blockSizeTgt = 1;
    int blockNumSrc = 1;
    int blockNumTgt = 1;
    int leadDimSizeSrc = s->dimSizeRDI[dimRDI];
    int leadDimSizeTgt = t->dimSizeRDI[dimRDI];
    int indexOffsetNum = 1;

    for (int i = 0; i < dimRDI; i++) {
        blockSizeSrc *= s->dimSizeRDI[i];
        blockSizeTgt *= t->dimSizeRDI[i];
    }
    for (int i = dimRDI; i < s->order; i++)
        blockNumSrc *= s->dimSizeRDI[i];
    for (int i = dimRDI; i < t->order; i++)
        blockNumTgt *= t->dimSizeRDI[i];

    CheckNTErrors((blockSizeSrc == blockSizeTgt), "Unmatched tensors!");
    indexOffsetNum = blockNumSrc / s->dimSizeRDI[dimRDI];

    int realIndexSize = indexOffsetNum * indexSize * copyNum;
    int * realSrcIndex = new int[realIndexSize];
    int * realTgtIndex = new int[realIndexSize];
    for (int i = 0; i < indexOffsetNum; i++) {
xiaotong committed
76 77 78
        int base = i * indexSize * copyNum;
        int baseSrc = i * leadDimSizeSrc;
        int baseTgt = i * leadDimSizeTgt;
xiaotong committed
79
        for (int j = 0; j < indexSize; j++) {
xiaotong committed
80 81 82
            int offset = base + j * copyNum;
            int * rsi = realSrcIndex + offset;
            int * rti = realTgtIndex + offset;
xiaotong committed
83
            for (int k = 0; k < copyNum; k++) {
xiaotong committed
84 85
                rsi[k] = baseSrc + srcIndex[j] + k;
                rti[k] = baseTgt + tgtIndex[j] + k;
xiaotong committed
86 87 88 89 90
            }
        }
    }

    for (int i = 0; i < indexSize; i++) {
xiaotong committed
91 92
        CheckNTErrors((srcIndex[i] < blockNumSrc), "Index is out of scope!");
        CheckNTErrors((tgtIndex[i] < blockNumTgt), "Index is out of scope!");
xiaotong committed
93 94
    }

95
    _CopyBlocks(s->data, blockSizeSrc * s->unitSize, realSrcIndex, realIndexSize, t->data, realTgtIndex, s->mem, s->devID);
xiaotong committed
96 97 98

    delete[] realSrcIndex;
    delete[] realTgtIndex;
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

/*
copy indexed sub-tensors (return a XTensor structure)
make a new tensor to keep the result and return it

>> s - the source tensor
>> dim - the leading dimension to define "sub-tensors"
         e.g., for a tensor of size (3, 2, 4) and dim = 2, 
         we have 4 sub-tensors of size (3,2)
>> srcIndex - index of the source sub-tensors
>> indexSize - length of srcIndex (and tgtIndex)
>> tgtIndex - index of the target sub-tensors
>> copyNum - number of the sub-tensors we copy for each source index, 
   e.g., for srcIndex = [1,4] and copyNum = 2,
   we actually copy the source sub-tensors 1, 2, 4, 5
<< return - the result of copying indexed sub-tensors
*/
XTensor CopyIndexed(const XTensor &s, int dim, int * srcIndex, int indexSize, int * tgtIndex, int copyNum)
{
119
    CheckNTErrors(dim >= 0 && dim < s.order, "A too larget dimension specified!");
120 121 122 123 124 125 126 127 128 129 130

    int order = s.order;
    int * dimSize = new int[order];

    for (int i = 0; i < s.order; i++) {
        if (i == dim)
            dimSize[i] = indexSize * copyNum;
        else
            dimSize[i] = s.dimSize[i];
    }
    
131 132
    float dr = (!s.isSparse) ? 1.0F : s.denseRatio;
    XTensor t(order, dimSize, s.dataType, dr, s.devID, s.mem);
133 134 135 136 137 138 139
    t.SetTMP();

    /* call _CopyIndexed function */
    _CopyIndexed(&s, &t, dim, srcIndex, indexSize, tgtIndex, copyNum);

    /* tensor connection */
    XLink::MakeLink(&s, NULL, &t, MOVEMENT_COPYINDEXED);
140
    XLink::AddParamToHeadInt(&t, dim);
141
    XLink::AddParamToHeadPointer(&t, srcIndex);
142
    XLink::AddParamToHeadInt(&t, indexSize);
143
    XLink::AddParamToHeadPointer(&t, tgtIndex);
144
    XLink::AddParamToHeadInt(&t, copyNum);
145 146 147 148
    
    /* destroy variables */
    delete[] dimSize;
    
149
    return t;
xiaotong committed
150 151 152
}

} // namespace nts(NiuTrans.Tensor)