gx
chenyc
2025-06-12 7b72ac13a83764a662159d4a49b7fffb90476ecb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
 * @license
 * Copyright 2020 Google LLC. 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.
 * =============================================================================
 */
import { backend_util, Conv2D, TensorBuffer, util } from '@tensorflow/tfjs-core';
import { assertNotComplex } from '../cpu_util';
export function conv2D(args) {
    const { inputs, backend, attrs } = args;
    const { x, filter } = inputs;
    const { strides, pad, dataFormat, dilations, dimRoundingMode } = attrs;
    assertNotComplex([x, filter], 'conv2d');
    const $dataFormat = backend_util.convertConv2DDataFormat(dataFormat);
    const convInfo = backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat);
    const filterHeight = convInfo.filterHeight;
    const filterWidth = convInfo.filterWidth;
    const dilationHeight = convInfo.dilationHeight;
    const dilationWidth = convInfo.dilationWidth;
    const padLeft = convInfo.padInfo.left;
    const padTop = convInfo.padInfo.top;
    const isChannelsLast = convInfo.dataFormat === 'channelsLast';
    const y = new TensorBuffer(convInfo.outShape, x.dtype);
    const xStrides = util.computeStrides(x.shape);
    const filterStrides = util.computeStrides(filter.shape);
    const xBatchStride = xStrides[0];
    const xRowStride = isChannelsLast ? xStrides[1] : xStrides[2];
    const xColStride = isChannelsLast ? xStrides[2] : 1;
    const xChannelStride = isChannelsLast ? 1 : xStrides[1];
    const yBatchStride = y.strides[0];
    const yRowStride = isChannelsLast ? y.strides[1] : y.strides[2];
    const yColStride = isChannelsLast ? y.strides[2] : 1;
    const yChannelStride = isChannelsLast ? 1 : y.strides[1];
    const xVals = backend.data.get(x.dataId).values;
    const wVals = backend.data.get(filter.dataId).values;
    const yVals = y.values;
    for (let b = 0; b < convInfo.batchSize; ++b) {
        const xOffset1 = b * xBatchStride;
        const yOffset1 = b * yBatchStride;
        for (let yR = 0; yR < convInfo.outHeight; ++yR) {
            const yOffset2 = yOffset1 + yR * yRowStride;
            const xRCorner = yR * convInfo.strideHeight - padTop;
            for (let wR = 0; wR < filterHeight; ++wR) {
                const xR = xRCorner + wR * dilationHeight;
                if (xR < 0 || xR >= convInfo.inHeight) {
                    continue;
                }
                const wOffset1 = wR * filterStrides[0];
                const xOffset2 = xOffset1 + xR * xRowStride;
                for (let yC = 0; yC < convInfo.outWidth; ++yC) {
                    const yOffset3 = yOffset2 + yC * yColStride;
                    const xCCorner = yC * convInfo.strideWidth - padLeft;
                    for (let wC = 0; wC < filterWidth; ++wC) {
                        const xC = xCCorner + wC * dilationWidth;
                        if (xC < 0 || xC >= convInfo.inWidth) {
                            continue;
                        }
                        const wOffset2 = wOffset1 + wC * filterStrides[1];
                        const xOffset3 = xOffset2 + xC * xColStride;
                        let wOffset3 = wOffset2;
                        for (let d1 = 0; d1 < convInfo.inChannels; ++d1) {
                            const xVal = xVals[xOffset3 + d1 * xChannelStride];
                            for (let d2 = 0; d2 < convInfo.outChannels; ++d2) {
                                yVals[yOffset3 + d2 * yChannelStride] +=
                                    xVal * wVals[wOffset3 + d2];
                            }
                            wOffset3 += convInfo.outChannels;
                        }
                    }
                }
            }
        }
    }
    return backend.makeTensorInfo(y.shape, y.dtype, yVals);
}
export const conv2DConfig = {
    kernelName: Conv2D,
    backendName: 'cpu',
    kernelFunc: conv2D
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29udjJELmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1iYWNrZW5kLWNwdS9zcmMva2VybmVscy9Db252MkQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFDLFlBQVksRUFBRSxNQUFNLEVBQXVELFlBQVksRUFBMEIsSUFBSSxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFHNUosT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sYUFBYSxDQUFDO0FBRTdDLE1BQU0sVUFBVSxNQUFNLENBQ2xCLElBQXlFO0lBRTNFLE1BQU0sRUFBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBQyxHQUFHLElBQUksQ0FBQztJQUN0QyxNQUFNLEVBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBQyxHQUFHLE1BQU0sQ0FBQztJQUMzQixNQUFNLEVBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLGVBQWUsRUFBQyxHQUFHLEtBQUssQ0FBQztJQUVyRSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUV4QyxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUMsdUJBQXVCLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDckUsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLGlCQUFpQixDQUMzQyxDQUFDLENBQUMsS0FBeUMsRUFDM0MsTUFBTSxDQUFDLEtBQXlDLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQ3pFLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBRXpELE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUM7SUFDM0MsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLFdBQVcsQ0FBQztJQUN6QyxNQUFNLGNBQWMsR0FBRyxRQUFR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S0FBSyxJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxFQUFFLEVBQUU7Z0NBQ2hELEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxHQUFHLGNBQWMsQ0FBQztvQ0FDakMsSUFBSSxHQUFHLEtBQUssQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDLENBQUM7NkJBQ2pDOzRCQUNELFFBQVEsSUFBSSxRQUFRLENBQUMsV0FBVyxDQUFDO3lCQUNsQztxQkFDRjtpQkFDRjthQUNGO1NBQ0Y7S0FDRjtJQUVELE9BQU8sT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDekQsQ0FBQztBQUVELE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBaUI7SUFDeEMsVUFBVSxFQUFFLE1BQU07SUFDbEIsV0FBVyxFQUFFLEtBQUs7SUFDbEIsVUFBVSxFQUFFLE1BQStCO0NBQzVDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCB7YmFja2VuZF91dGlsLCBDb252MkQsIENvbnYyREF0dHJzLCBDb252MkRJbnB1dHMsIEtlcm5lbENvbmZpZywgS2VybmVsRnVuYywgVGVuc29yQnVmZmVyLCBUZW5zb3JJbmZvLCBUeXBlZEFycmF5LCB1dGlsfSBmcm9tICdAdGVuc29yZmxvdy90ZmpzLWNvcmUnO1xuXG5pbXBvcnQge01hdGhCYWNrZW5kQ1BVfSBmcm9tICcuLi9iYWNrZW5kX2NwdSc7XG5pbXBvcnQge2Fzc2VydE5vdENvbXBsZXh9IGZyb20gJy4uL2NwdV91dGlsJztcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnYyRChcbiAgICBhcmdzOiB7aW5wdXRzOiBDb252MkRJbnB1dHMsIGJhY2tlbmQ6IE1hdGhCYWNrZW5kQ1BVLCBhdHRyczogQ29udjJEQXR0cnN9KTpcbiAgICBUZW5zb3JJbmZvIHtcbiAgY29uc3Qge2lucHV0cywgYmFja2VuZCwgYXR0cnN9ID0gYXJncztcbiAgY29uc3Qge3gsIGZpbHRlcn0gPSBpbnB1dHM7XG4gIGNvbnN0IHtzdHJpZGVzLCBwYWQsIGRhdGFGb3JtYXQsIGRpbGF0aW9ucywgZGltUm91bmRpbmdNb2RlfSA9IGF0dHJzO1xuXG4gIGFzc2VydE5vdENvbXBsZXgoW3gsIGZpbHRlcl0sICdjb252MmQnKTtcblxuICBjb25zdCAkZGF0YUZvcm1hdCA9IGJhY2tlbmRfdXRpbC5jb252ZXJ0Q29udjJERGF0YUZvcm1hdChkYXRhRm9ybWF0KTtcbiAgY29uc3QgY29udkluZm8gPSBiYWNrZW5kX3V0aWwuY29tcHV0ZUNvbnYyREluZm8oXG4gICAgICB4LnNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLFxuICAgICAgZmlsdGVyLnNoYXBlIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLCBzdHJpZGVzLCBkaWxhdGlvbnMsIHBhZCxcbiAgICAgIGRpbVJvdW5kaW5nTW9kZSwgZmFsc2UgLyogZGVwdGh3aXNlICovLCAkZGF0YUZvcm1hdCk7XG5cbiAgY29uc3QgZmlsdGVySGVpZ2h0ID0gY29udkluZm8uZmlsdGVySGVpZ2h0O1xuICBjb25zdCBmaWx0ZXJXaWR0aCA9IGNvbnZJbmZvLmZpbHRlcldpZHRoO1xuICBjb25zdCBkaWxhdGlvbkhlaWdodCA9IGNvbnZJbmZvLmRpbGF0aW9uSGVpZ2h0O1xuICBjb25zdCBkaWxhdGlvbldpZHRoID0gY29udkluZm8uZGlsYXRpb25XaWR0aDtcbiAgY29uc3QgcGFkTGVmdCA9IGNvbnZJbmZvLnBhZEluZm8ubGVmdDtcbiAgY29uc3QgcGFkVG9wID0gY29udkluZm8ucGFkSW5mby50b3A7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gY29udkluZm8uZGF0YUZvcm1hdCA9PT0gJ2NoYW5uZWxzTGFzdCc7XG5cbiAgY29uc3QgeSA9IG5ldyBUZW5zb3JCdWZmZXIoY29udkluZm8ub3V0U2hhcGUsIHguZHR5cGUgYXMgJ2Zsb2F0MzInKTtcblxuICBjb25zdCB4U3RyaWRlcyA9IHV0aWwuY29tcHV0ZVN0cmlkZXMoeC5zaGFwZSk7XG4gIGNvbnN0IGZpbHRlclN0cmlkZXMgPSB1dGlsLmNvbXB1dGVTdHJpZGVzKGZpbHRlci5zaGFwZSk7XG5cbiAgY29uc3QgeEJhdGNoU3RyaWRlID0geFN0cmlkZXNbMF07XG4gIGNvbnN0IHhSb3dTdHJpZGUgPSBpc0NoYW5uZWxzTGFzdCA/IHhTdHJpZGVzWzFdIDogeFN0cmlkZXNbMl07XG4gIGNvbnN0IHhDb2xTdHJpZGUgPSBpc0NoYW5uZWxzTGFzdCA/IHhTdHJpZGVzWzJdIDogMTtcbiAgY29uc3QgeENoYW5uZWxTdHJpZGUgPSBpc0NoYW5uZWxzTGFzdCA/IDEgOiB4U3RyaWRlc1sxXTtcbiAgY29uc3QgeUJhdGNoU3RyaWRlID0geS5zdHJpZGVzWzBdO1xuICBjb25zdCB5Um93U3RyaWRlID0gaXNDaGFubmVsc0xhc3QgPyB5LnN0cmlkZXNbMV0gOiB5LnN0cmlkZXNbMl07XG4gIGNvbnN0IHlDb2xTdHJpZGUgPSBpc0NoYW5uZWxzTGFzdCA/IHkuc3RyaWRlc1syXSA6IDE7XG4gIGNvbnN0IHlDaGFubmVsU3RyaWRlID0gaXNDaGFubmVsc0xhc3QgPyAxIDogeS5zdHJpZGVzWzFdO1xuXG4gIGNvbnN0IHhWYWxzID0gYmFja2VuZC5kYXRhLmdldCh4LmRhdGFJZCkudmFsdWVzIGFzIFR5cGVkQXJyYXk7XG4gIGNvbnN0IHdWYWxzID0gYmFja2VuZC5kYXRhLmdldChmaWx0ZXIuZGF0YUlkKS52YWx1ZXMgYXMgVHlwZWRBcnJheTtcbiAgY29uc3QgeVZhbHMgPSB5LnZhbHVlcztcblxuICBmb3IgKGxldCBiID0gMDsgYiA8IGNvbnZJbmZvLmJhdGNoU2l6ZTsgKytiKSB7XG4gICAgY29uc3QgeE9mZnNldDEgPSBiICogeEJhdGNoU3RyaWRlO1xuICAgIGNvbnN0IHlPZmZzZXQxID0gYiAqIHlCYXRjaFN0cmlkZTtcbiAgICBmb3IgKGxldCB5UiA9IDA7IHlSIDwgY29udkluZm8ub3V0SGVpZ2h0OyArK3lSKSB7XG4gICAgICBjb25zdCB5T2Zmc2V0MiA9IHlPZmZzZXQxICsgeVIgKiB5Um93U3RyaWRlO1xuICAgICAgY29uc3QgeFJDb3JuZXIgPSB5UiAqIGNvbnZJbmZvLnN0cmlkZUhlaWdodCAtIHBhZFRvcDtcbiAgICAgIGZvciAobGV0IHdSID0gMDsgd1IgPCBmaWx0ZXJIZWlnaHQ7ICsrd1IpIHtcbiAgICAgICAgY29uc3QgeFIgPSB4UkNvcm5lciArIHdSICogZGlsYXRpb25IZWlnaHQ7XG4gICAgICAgIGlmICh4UiA8IDAgfHwgeFIgPj0gY29udkluZm8uaW5IZWlnaHQpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB3T2Zmc2V0MSA9IHdSICogZmlsdGVyU3RyaWRlc1swXTtcbiAgICAgICAgY29uc3QgeE9mZnNldDIgPSB4T2Zmc2V0MSArIHhSICogeFJvd1N0cmlkZTtcbiAgICAgICAgZm9yIChsZXQgeUMgPSAwOyB5QyA8IGNvbnZJbmZvLm91dFdpZHRoOyArK3lDKSB7XG4gICAgICAgICAgY29uc3QgeU9mZnNldDMgPSB5T2Zmc2V0MiArIHlDICogeUNvbFN0cmlkZTtcbiAgICAgICAgICBjb25zdCB4Q0Nvcm5lciA9IHlDICogY29udkluZm8uc3RyaWRlV2lkdGggLSBwYWRMZWZ0O1xuICAgICAgICAgIGZvciAobGV0IHdDID0gMDsgd0MgPCBmaWx0ZXJXaWR0aDsgKyt3Qykge1xuICAgICAgICAgICAgY29uc3QgeEMgPSB4Q0Nvcm5lciArIHdDICogZGlsYXRpb25XaWR0aDtcbiAgICAgICAgICAgIGlmICh4QyA8IDAgfHwgeEMgPj0gY29udkluZm8uaW5XaWR0aCkge1xuICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHdPZmZzZXQyID0gd09mZnNldDEgKyB3QyAqIGZpbHRlclN0cmlkZXNbMV07XG4gICAgICAgICAgICBjb25zdCB4T2Zmc2V0MyA9IHhPZmZzZXQyICsgeEMgKiB4Q29sU3RyaWRlO1xuICAgICAgICAgICAgbGV0IHdPZmZzZXQzID0gd09mZnNldDI7XG4gICAgICAgICAgICBmb3IgKGxldCBkMSA9IDA7IGQxIDwgY29udkluZm8uaW5DaGFubmVsczsgKytkMSkge1xuICAgICAgICAgICAgICBjb25zdCB4VmFsID0geFZhbHNbeE9mZnNldDMgKyBkMSAqIHhDaGFubmVsU3RyaWRlXTtcbiAgICAgICAgICAgICAgZm9yIChsZXQgZDIgPSAwOyBkMiA8IGNvbnZJbmZvLm91dENoYW5uZWxzOyArK2QyKSB7XG4gICAgICAgICAgICAgICAgeVZhbHNbeU9mZnNldDMgKyBkMiAqIHlDaGFubmVsU3RyaWRlXSArPVxuICAgICAgICAgICAgICAgICAgICB4VmFsICogd1ZhbHNbd09mZnNldDMgKyBkMl07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgd09mZnNldDMgKz0gY29udkluZm8ub3V0Q2hhbm5lbHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJhY2tlbmQubWFrZVRlbnNvckluZm8oeS5zaGFwZSwgeS5kdHlwZSwgeVZhbHMpO1xufVxuXG5leHBvcnQgY29uc3QgY29udjJEQ29uZmlnOiBLZXJuZWxDb25maWcgPSB7XG4gIGtlcm5lbE5hbWU6IENvbnYyRCxcbiAgYmFja2VuZE5hbWU6ICdjcHUnLFxuICBrZXJuZWxGdW5jOiBjb252MkQgYXMgdW5rbm93biBhcyBLZXJuZWxGdW5jXG59O1xuIl19