MCPcopy Create free account
hub / github.com/NVIDIA/TensorRT / enqueue

Method enqueue

samples/python/onnx_custom_plugin/plugin/customHardmaxPlugin.cpp:152–233  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

150void HardmaxPlugin::detachFromContext() noexcept {}
151
152int32_t HardmaxPlugin::enqueue(nvinfer1::PluginTensorDesc const* inputDesc,
153 nvinfer1::PluginTensorDesc const* outputDesc, void const* const* inputs, void* const* outputs, void* workspace,
154 cudaStream_t stream) noexcept
155{
156 if (inputDesc[0].type != nvinfer1::DataType::kFLOAT)
157 {
158 return -1;
159 }
160
161 CUBLAS_CALL(cublasSetStream(mCublas, stream));
162
163 auto const* data = static_cast<float const*>(inputs[0]);
164 auto* result = static_cast<float*>(outputs[0]);
165
166 // Make sure output is initialized to all 0's.
167 // Later we will set the correct outputs to be 1's and not touch the rest.
168 CUDA_CALL(cudaMemsetAsync(result, 0, mDimProductOuter * mDimProductInner * mAxisSize * sizeof(float), stream));
169
170 // We use the workspace in the case that the first call to 'cublasIsamax' is insufficient.
171 // The first half of the workspace we use to copy the values of the axis into, so that we can
172 // subtract out the minimum value and call 'cublasIsamax' again. See the comment below.
173 // The second half of the workspace will be a costant array of 1's, necessary for our cublasSaxpy call.
174 auto* const axisFlat = static_cast<float* const>(workspace);
175 float* const ones = axisFlat + mAxisSize;
176 float const one = 1.0F;
177 CUDRIVER_CALL(cuMemsetD32Async(CUdeviceptr(ones), *reinterpret_cast<int const*>(&one), mAxisSize, stream));
178
179 // This plugin works by parallelizing the argmax operation along a single axis.
180 // This is efficient when the axis size is very large compared to the other dimensions.
181 //
182 // Consider an input shape (1, 512, 3) with axis = 1. This plugin will perform well because
183 // the work which is parallelized is over the large 512-element-long axis, and the work that is done
184 // serially is over the small 1-element-long and 3-element-long axes.
185 //
186 // However, when the axis size is small compared to the other dimensions, this plugin will be very
187 // inefficient. If the input shape is (1, 512, 3) and the hardmax is over axis = 2, then
188 // the work is parallelized over the small 3-element-long axis and the work is done serially over
189 // the large 512-element-long axis. A smarter plugin would try to recognize this and parallelize
190 // the work which would take longest.
191 for (int32_t outer = 0; outer < mDimProductOuter; outer++)
192 {
193 for (int32_t inner = 0; inner < mDimProductInner; inner++)
194 {
195 int32_t const axesOffset = outer * mDimProductInner * mAxisSize + inner;
196 float const* arr = &data[axesOffset];
197 int32_t const stride = mDimProductInner;
198 int32_t argmaxResult;
199 CUBLAS_CALL(cublasIsamax(mCublas, mAxisSize, arr, stride, &argmaxResult));
200
201 // cublasIsamax returns 1-indexed so convert to 0-indexed
202 argmaxResult--;
203
204 // cublasIsamax returns the index of the element with the highest absolute value.
205 // If this element is positive, then we know it is also the max.
206 // However, if it is negative, we need to
207 // 1) Copy the axis into our workspace
208 // 2) Subtract the minimum value we found from our array. This ensures that
209 // none of the values are negative, and that the largest element remains

Callers 2

stepOnceMethod · 0.45
operator()Method · 0.45

Calls

no outgoing calls

Tested by

no test coverage detected