/* * SPDX-FileCopyrightText: Copyright (c) 1993-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 * * 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. */ #include "common/kernels/kernel.h" namespace nvinfer1 { namespace plugin { #define CUBLAS_CHECK(condition) \ do \ { \ cublasStatus_t status = condition; \ if (status != CUBLAS_STATUS_SUCCESS) \ { \ printf("%s %d CUBLAS FAIL %s\n", __FILE__, __LINE__, cublasGetErrorString(status)); \ } \ } while (0) // this scatter kernel works on a 2d table writing rows // index is 1-D array // updates is 2-D array // output is 2-D array // output[index[i]] = updates[i] __global__ void scatterKernel( char* output, const char* updates, const int* indices, int pitch, int rowSize) { int idx = indices[blockIdx.x]; char* pDst = (char*)output + idx * pitch; const char* pSrc = updates + blockIdx.x * rowSize; memcpy(pDst, pSrc, rowSize); } // Transform nd index to 1 - d index __global__ void transformIdxKernel( int* output, const int* transformCoeff, // these are actually the output pitches of the respective dimensions const int* indices, int sliceRank) { const int* idx = indices + sliceRank * blockIdx.x; int transformedIdx = 0; for (int i = 0; i < sliceRank; i++) { transformedIdx += idx[i] * transformCoeff[i]; } output[blockIdx.x] = transformedIdx; } pluginStatus_t scatterNDInference( cudaStream_t stream, int* transformCoeff, int nOutputDims, int sliceRank, int nRows, int rowSize, int copySize, int sizeOfElementInBytes, const void* index, const void* updates, const void* data, void* output, void* workspace) { const int* _index = (const int*)(index); const char* _updates = (const char*)(updates); char* _output = (char*)(output); int* wo = (int*)(workspace); int* transformedIdx = wo + sizeof(int)*nOutputDims; int* deviceTransformCoeff = wo; CSC(cudaMemcpy(workspace, transformCoeff, sizeof(int) * nOutputDims, cudaMemcpyHostToDevice), STATUS_FAILURE); transformIdxKernel<<>>(transformedIdx, deviceTransformCoeff, _index, sliceRank); CSC(cudaMemcpy(output, data, copySize, cudaMemcpyDeviceToDevice), STATUS_FAILURE); // assuming output pitch = rowSize i.e no padding scatterKernel<<>>(_output, _updates, transformedIdx, rowSize * 4, rowSize * 4); return STATUS_SUCCESS; } } // namespace plugin } // namespace nvinfer1