/* * Copyright (c) 2022-2024, NVIDIA CORPORATION. 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. */ #include "tensorrt_llm/kernels/penaltyTypes.h" #include "tests/kernels/sampling/samplingTest.h" using namespace tensorrt_llm::tests::kernels::sampling; namespace { namespace tc = tensorrt_llm::common; namespace tk = tensorrt_llm::kernels; using TensorPtr = tensorrt_llm::runtime::ITensor::SharedPtr; using namespace tensorrt_llm::runtime; using namespace tensorrt_llm::kernels; struct TemperatureTestParam { int32_t batchSize; int32_t vocabSize; TensorPtr temperatures; int32_t temperaturesSize; TemperatureTestParam& setBatchSize(int32_t bs) { batchSize = bs; return *this; } TemperatureTestParam& setVocabSize(int32_t vs) { vocabSize = vs; return *this; } TemperatureTestParam& setTemperaturesSize(int32_t ts) { temperaturesSize = ts; return *this; } TemperatureTestParam& setTemperatures(TensorPtr temp) { temperatures = temp; return *this; } std::string toString() const { return tc::fmtstr("TemperatureTestParam[batch=%d, vocab=%d, temperatures=%s]", batchSize, vocabSize, tc::arr2str(bufferCast(*temperatures), temperaturesSize).c_str()); } }; size_t padVocabSize(size_t vocabSize, size_t pad = 8) { return (vocabSize + pad - 1) / pad * pad; } template void initLogitsAndBias( T* logits, T* bias, const size_t batchSize, const size_t vocabSize, const size_t mVocabSizepadded) { initRandom(logits, batchSize * mVocabSizepadded, -5.0f, 5.0f); if (bias != nullptr) { initRandom(bias, vocabSize, -5.0f, 5.0f); } bool is_half = sizeof(T) == 2; for (size_t i = 0; i < batchSize; ++i) { for (size_t j = 0; j < mVocabSizepadded; ++j) { if (j >= vocabSize) { logits[i * mVocabSizepadded + j] = static_cast(is_half ? -65504.f : -FLT_MAX); if (bias != nullptr && i == 0) { bias[j] = (T) 0.0f; } } } } } /////////////////////////////////// Tests ////////////////////////////////////////// template class TemperaturePenaltyTest : public SamplingKernelTest { protected: // Set up test int32_t mMaxBatchSize; int32_t mBatchSize; int32_t mVocabSize; int32_t mVocabSizePadded; using SamplingKernelTest::mBufferManager; using SamplingKernelTest::mStream; using SamplingKernelTest::mLogitsHost; TensorPtr mLogitsDevice; TensorPtr mPenaltyWorkspaceDevice; TensorPtr mBiasHost; TensorPtr mBiasDevice; TensorPtr mTemperaturesDevice; TensorPtr mBatchSlots; void subsetup(const TemperatureTestParam& param) { mBatchSize = param.batchSize; mMaxBatchSize = 2 * mBatchSize; mVocabSize = param.vocabSize; mVocabSizePadded = padVocabSize(mVocabSize); mLogitsHost = mBufferManager->pinned(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mLogitsDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mPenaltyWorkspaceDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSize}), nvinfer1::DataType::kINT32); mBiasHost = mBufferManager->pinned(ITensor::makeShape({mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mBiasDevice = mBufferManager->gpu(ITensor::makeShape({mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mBatchSlots = mBufferManager->pinned(ITensor::makeShape({mBatchSize}), nvinfer1::DataType::kINT32); auto batchSlotsPtr = bufferCast(*mBatchSlots); for (SizeType bi = 0; bi < mBatchSize; ++bi) { batchSlotsPtr[bi] = 2 * bi; } initLogitsAndBias( bufferCast(*mLogitsHost), bufferCast(*mBiasHost), mBatchSize, mVocabSize, mVocabSizePadded); mBufferManager->copy(*mLogitsHost, *mLogitsDevice); mBufferManager->copy(*mBiasHost, *mBiasDevice); ASSERT_EQ(param.temperaturesSize, mMaxBatchSize) << "Invalid test configuration."; mTemperaturesDevice = mBufferManager->gpu(ITensor::makeShape({param.temperaturesSize}), nvinfer1::DataType::kFLOAT); mBufferManager->copy(*param.temperatures, *mTemperaturesDevice); } void computeReference(T* logits, const T* bias, const float* temperatures, const size_t temperaturesSize) { const bool IS_FP16 = std::is_same::value; const T MAX_T_VAL = (IS_FP16) ? 65504.F : FLT_MAX; auto const batchSlotsPtr = bufferCast(*mBatchSlots); for (size_t bi = 0; bi < mBatchSize; ++bi) { auto const batchSlot = batchSlotsPtr[bi]; float temperature = temperatures[batchSlot]; ASSERT_GT(temperature, 0.0f) << "temperature should be positive but got " << temperature; for (size_t j = 0; j < mVocabSizePadded; ++j) { size_t index = bi * mVocabSizePadded + j; float logit = static_cast(logits[index]); if (j < mVocabSize && bias != nullptr) { logit += static_cast(bias[j]); } logits[index] = j < mVocabSize ? static_cast(logit / temperature) : -MAX_T_VAL; } } } public: void runTest(TemperatureTestParam param) { subsetup(param); // Do test InvokeBatchApplyPenaltyParams penalty_params{bufferCast(*mLogitsDevice), bufferCast(*mBiasDevice), bufferCast(*mPenaltyWorkspaceDevice), nullptr, bufferCast(*mTemperaturesDevice), nullptr, nullptr, nullptr, false, static_cast(mBatchSize), 1, 1, static_cast(mVocabSize), static_cast(mVocabSizePadded), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, bufferCast(*mBatchSlots), mStream->get()}; tk::invokeBatchApplyPenalty(penalty_params); auto logitsOutHost = mBufferManager->copyFrom(*mLogitsDevice, MemoryType::kCPU); mStream->synchronize(); computeReference(bufferCast(*mLogitsHost), bufferCast(*mBiasHost), bufferCast(*param.temperatures), param.temperaturesSize); bool passed = checkResult(param.toString(), bufferCast(*logitsOutHost), bufferCast(*mLogitsHost), mBatchSize * mVocabSizePadded); EXPECT_TRUE(passed); } }; TYPED_TEST_SUITE(TemperaturePenaltyTest, FloatAndHalfTypes); TYPED_TEST(TemperaturePenaltyTest, NoPenalty) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr temperaturesHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*temperaturesHost)[i] = 1.0f; } this->runTest(TemperatureTestParam() .setBatchSize(batchSize) .setVocabSize(4) .setTemperaturesSize(maxBatchSize) .setTemperatures(temperaturesHost)); } TYPED_TEST(TemperaturePenaltyTest, LessThanOne) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr temperaturesHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*temperaturesHost)[i] = 0.53f; } this->runTest(TemperatureTestParam() .setBatchSize(batchSize) .setVocabSize(4) .setTemperaturesSize(maxBatchSize) .setTemperatures(temperaturesHost)); } TYPED_TEST(TemperaturePenaltyTest, GreaterThaneOne) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr temperaturesHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*temperaturesHost)[i] = 2.01f; } this->runTest(TemperatureTestParam() .setBatchSize(batchSize) .setVocabSize(4) .setTemperaturesSize(maxBatchSize) .setTemperatures(temperaturesHost)); } TYPED_TEST(TemperaturePenaltyTest, Mixed) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr temperaturesHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*temperaturesHost)[i] = 0.53f + 0.2f * i; } this->runTest(TemperatureTestParam() .setBatchSize(batchSize) .setVocabSize(4) .setTemperaturesSize(maxBatchSize) .setTemperatures(temperaturesHost)); } TYPED_TEST(TemperaturePenaltyTest, LargeVocab) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr temperaturesHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*temperaturesHost)[i] = 0.53f + 0.2f * i; } this->runTest(TemperatureTestParam() .setBatchSize(batchSize) .setVocabSize(50001) .setTemperaturesSize(maxBatchSize) .setTemperatures(temperaturesHost)); } struct RepetitionPenaltyTestCase { int32_t batchSize; int32_t vocabSize; int32_t maxInputLength; TensorPtr repetitionPenalties; TensorPtr presencePenalties; TensorPtr frequencyPenalties; int32_t repetitionPenaltiesSize; int32_t presencePenaltiesSize; int32_t frequencyPenaltiesSize; RepetitionPenaltyTestCase& setBatchSize(int32_t bs) { batchSize = bs; return *this; } RepetitionPenaltyTestCase& setVocabSize(int32_t vs) { vocabSize = vs; return *this; } RepetitionPenaltyTestCase& setMaxInputLength(int32_t len) { maxInputLength = len; return *this; } RepetitionPenaltyTestCase& setRepetitionPenalties(TensorPtr rp) { repetitionPenalties = rp; return *this; } RepetitionPenaltyTestCase& setPresencePenalties(TensorPtr pp) { presencePenalties = pp; return *this; } RepetitionPenaltyTestCase& setFrequencyPenalties(TensorPtr fp) { frequencyPenalties = fp; return *this; } RepetitionPenaltyTestCase& setRepetitionPenaltiesSize(int32_t rps) { repetitionPenaltiesSize = rps; return *this; } RepetitionPenaltyTestCase& setPresencePenaltiesSize(int32_t pps) { presencePenaltiesSize = pps; return *this; } RepetitionPenaltyTestCase& setFrequencyPenaltiesSize(int32_t fps) { frequencyPenaltiesSize = fps; return *this; } std::string toString() const { return tc::fmtstr( "RepetitionPenaltyTestCase[batch=%d, vocab=%d, maxInputLength=%d, " "repetitionPenalties=%s, presencePenalties=%s, frequencyPenalties=%s]", batchSize, vocabSize, maxInputLength, tc::arr2str(bufferCast(*repetitionPenalties), repetitionPenaltiesSize).c_str(), tc::arr2str(bufferCast(*presencePenalties), presencePenaltiesSize).c_str(), tc::arr2str(bufferCast(*frequencyPenalties), frequencyPenaltiesSize).c_str()); } }; template class RepetitionPenaltyTest : public SamplingKernelTest { protected: // Set up test int32_t mBatchSize; int32_t mMaxBatchSize; int32_t mVocabSize; int32_t mVocabSizePadded; int32_t mMaxInputLength; int32_t mSequenceLength; using SamplingKernelTest::mBufferManager; using SamplingKernelTest::mStream; using SamplingKernelTest::mLogitsHost; TensorPtr mLogitsDevice; TensorPtr mPenaltyWorkspaceDevice; TensorPtr mOutputIdsHost; TensorPtr mOutputIdsDevice; TensorPtr mContextLengthHost; TensorPtr mContextLengthDevice; TensorPtr mSeqLengthHost; TensorPtr mSeqLengthDevice; TensorPtr mIdsPtrHost; TensorPtr mIdsPtrDevice; TensorPtr mRepetitionPenaltiesDevice; TensorPtr mPresencePenaltiesDevice; TensorPtr mFrequencyPenaltiesDevice; TensorPtr mBatchSlots; void subsetup(RepetitionPenaltyTestCase param) { mBatchSize = param.batchSize; mMaxBatchSize = 2 * mBatchSize; mVocabSize = param.vocabSize; mVocabSizePadded = padVocabSize(mVocabSize); mMaxInputLength = param.maxInputLength; mSequenceLength = 2 * mMaxInputLength; // input + output mLogitsHost = mBufferManager->pinned(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mLogitsDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mPenaltyWorkspaceDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSize}), nvinfer1::DataType::kINT32); mOutputIdsHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize, mSequenceLength}), nvinfer1::DataType::kINT32); mOutputIdsDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize, mSequenceLength}), nvinfer1::DataType::kINT32); mSeqLengthHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mSeqLengthDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mContextLengthHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mContextLengthDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mIdsPtrHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT64); mIdsPtrDevice = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT64); mBatchSlots = mBufferManager->pinned(ITensor::makeShape({mBatchSize}), nvinfer1::DataType::kINT32); auto batchSlotsPtr = bufferCast(*mBatchSlots); for (SizeType bi = 0; bi < mBatchSize; ++bi) { batchSlotsPtr[bi] = 2 * bi; } initLogitsAndBias( bufferCast(*mLogitsHost), static_cast(nullptr), mBatchSize, mVocabSize, mVocabSizePadded); initRandomInt(bufferCast(*mOutputIdsHost), mSequenceLength * mMaxBatchSize, 0, mVocabSize); initRandomInt(bufferCast(*mSeqLengthHost), mMaxBatchSize, 1, mSequenceLength); for (size_t i = 0; i < mMaxBatchSize; ++i) { bufferCast(*mContextLengthHost)[i] = bufferCast(*mSeqLengthHost)[i]; } auto idsPtrHostPtr = reinterpret_cast(bufferCast(*mIdsPtrHost)); auto outputIdsDevicePtr = bufferCast(*mOutputIdsDevice); for (SizeType bi = 0; bi < mMaxBatchSize; bi++) { idsPtrHostPtr[bi] = outputIdsDevicePtr + bi * mSequenceLength; } mBufferManager->copy(*mLogitsHost, *mLogitsDevice); mBufferManager->copy(*mOutputIdsHost, *mOutputIdsDevice); mBufferManager->copy(*mContextLengthHost, *mContextLengthDevice); mBufferManager->copy(*mSeqLengthHost, *mSeqLengthDevice); mBufferManager->copy(*mIdsPtrHost, *mIdsPtrDevice); ASSERT_EQ(param.repetitionPenaltiesSize, mMaxBatchSize) << "Invalid test configuration."; ASSERT_EQ(param.presencePenaltiesSize, mMaxBatchSize) << "Invalid test configuration."; ASSERT_EQ(param.frequencyPenaltiesSize, mMaxBatchSize) << "Invalid test configuration."; mRepetitionPenaltiesDevice = mBufferManager->gpu(ITensor::makeShape({param.repetitionPenaltiesSize}), nvinfer1::DataType::kFLOAT); mPresencePenaltiesDevice = mBufferManager->gpu(ITensor::makeShape({param.presencePenaltiesSize}), nvinfer1::DataType::kFLOAT); mFrequencyPenaltiesDevice = mBufferManager->gpu(ITensor::makeShape({param.frequencyPenaltiesSize}), nvinfer1::DataType::kFLOAT); mBufferManager->copy(*param.repetitionPenalties, *mRepetitionPenaltiesDevice); mBufferManager->copy(*param.presencePenalties, *mPresencePenaltiesDevice); mBufferManager->copy(*param.frequencyPenalties, *mFrequencyPenaltiesDevice); } void computeReference(T* logits, const int* outputIds, const int* sequenceLengths, const float* repetitionPenalties, const float* presencePenalties, const float* frequencyPenalties, const int32_t repetitionPenaltiesSize, const int32_t presencePenaltiesSize, const int32_t frequencyPenaltiesSize) { std::vector penalized(mVocabSize); auto batchSlotsPtr = bufferCast(*mBatchSlots); for (int32_t bi = 0; bi < mBatchSize; ++bi) { auto const batchSlot = batchSlotsPtr[bi]; float repetitionPenalty = repetitionPenaltiesSize > 1 ? repetitionPenalties[batchSlot] : repetitionPenalties[0]; float presencePenalty = presencePenaltiesSize > 1 ? presencePenalties[batchSlot] : presencePenalties[0]; float frequencyPenalty = frequencyPenaltiesSize > 1 ? frequencyPenalties[batchSlot] : frequencyPenalties[0]; std::fill(penalized.begin(), penalized.end(), false); size_t offset = bi * mVocabSizePadded; const auto step = sequenceLengths[batchSlot]; for (int32_t t = 0; t < step; ++t) { int tokenId = outputIds[batchSlot * mSequenceLength + t]; if (!penalized[tokenId]) { float logit = static_cast(logits[offset + tokenId]); logits[offset + tokenId] = static_cast( (logit < 0.0f ? logit * repetitionPenalty : logit / repetitionPenalty) - presencePenalty); penalized[tokenId] = true; } logits[offset + tokenId] -= frequencyPenalty; } } } public: void runTest(RepetitionPenaltyTestCase param) { subsetup(param); InvokeBatchApplyPenaltyParams penalty_params{bufferCast(*mLogitsDevice), nullptr, bufferCast(*mPenaltyWorkspaceDevice), nullptr, nullptr, bufferCast(*mRepetitionPenaltiesDevice), bufferCast(*mPresencePenaltiesDevice), bufferCast(*mFrequencyPenaltiesDevice), true, static_cast(mBatchSize), 1, mSequenceLength, static_cast(mVocabSize), static_cast(mVocabSizePadded), reinterpret_cast(bufferCast(*mIdsPtrDevice)), nullptr, bufferCast(*mContextLengthDevice), bufferCast(*mSeqLengthDevice), nullptr, nullptr, bufferCast(*mBatchSlots), mStream->get()}; tk::invokeBatchApplyPenalty(penalty_params); auto logitsOutHost = mBufferManager->copyFrom(*mLogitsDevice, MemoryType::kCPU); computeReference(bufferCast(*mLogitsHost), bufferCast(*mOutputIdsHost), bufferCast(*mSeqLengthHost), bufferCast(*param.repetitionPenalties), bufferCast(*param.presencePenalties), bufferCast(*param.frequencyPenalties), param.repetitionPenaltiesSize, param.presencePenaltiesSize, param.frequencyPenaltiesSize); mStream->synchronize(); bool passed = checkResult(param.toString(), bufferCast(*logitsOutHost), bufferCast(*mLogitsHost), mBatchSize * mVocabSizePadded); EXPECT_TRUE(passed); } }; TYPED_TEST_SUITE(RepetitionPenaltyTest, FloatAndHalfTypes); TYPED_TEST(RepetitionPenaltyTest, BatchNoPenalty) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchRepetitionLessThanOne) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 0.53f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchRepetitionGreaterThaneOne) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 2.01f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchRepetitionMixed) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchPresenceMixed) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchPresenceHasDefaultValueZero2) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = i % 2 == 0 ? 1.0f : 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchFrequencyMixed) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.53 + i * 0.2f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, BatchFrequencyHasDefaultValueZero2) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = i % 2 == 0 ? 1.0f : 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, PenaltyTypeRepetitionPresence) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*presencePenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*frequencyPenaltyHost)[i] = 0.0f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, PenaltyTypeRepetitionFrequency) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*presencePenaltyHost)[i] = 0.0f; bufferCast(*frequencyPenaltyHost)[i] = 0.53 + i * 0.2f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, PenaltyTypePresenceFrequency) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 1.0f; bufferCast(*presencePenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*frequencyPenaltyHost)[i] = 0.53 + i * 0.2f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } TYPED_TEST(RepetitionPenaltyTest, PenaltyTypeFull) { int32_t batchSize = 6; int32_t maxBatchSize = 2 * batchSize; TensorPtr repetitionPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr presencePenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); TensorPtr frequencyPenaltyHost = this->mBufferManager->pinned(ITensor::makeShape({maxBatchSize}), nvinfer1::DataType::kFLOAT); for (int32_t i = 0; i < maxBatchSize; ++i) { bufferCast(*repetitionPenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*presencePenaltyHost)[i] = 0.53 + i * 0.2f; bufferCast(*frequencyPenaltyHost)[i] = 0.53 + i * 0.2f; } this->runTest(RepetitionPenaltyTestCase() .setBatchSize(batchSize) .setVocabSize(4) .setMaxInputLength(5) .setRepetitionPenalties(repetitionPenaltyHost) .setPresencePenalties(presencePenaltyHost) .setFrequencyPenalties(frequencyPenaltyHost) .setRepetitionPenaltiesSize(maxBatchSize) .setPresencePenaltiesSize(maxBatchSize) .setFrequencyPenaltiesSize(maxBatchSize)); } struct MinLengthPenaltyTestParams { int32_t batchSize; int32_t vocabSize; int32_t maxSeqLength; MinLengthPenaltyTestParams& setBatchSize(int32_t bs) { batchSize = bs; return *this; } MinLengthPenaltyTestParams& setVocabSize(int32_t vs) { vocabSize = vs; return *this; } MinLengthPenaltyTestParams& setMaxSeqLength(int32_t sl) { maxSeqLength = sl; return *this; } std::string toString() const { return tc::fmtstr( "MinLengthPenaltyTestParams[batch=%d, vocab=%d, maxSeqLen=%d]", batchSize, vocabSize, maxSeqLength); } }; template class MinLengthPenaltyTest : public SamplingKernelTest { protected: // Set up test int32_t mBatchSize; int32_t mMaxBatchSize; int32_t mVocabSize; int32_t mVocabSizePadded; int32_t mMaxInputLength; int32_t mSequenceLength; using SamplingKernelTest::mBufferManager; using SamplingKernelTest::mStream; using SamplingKernelTest::mLogitsHost; TensorPtr mLogitsDevice; TensorPtr mPenaltyWorkspaceDevice; TensorPtr mContextLengthHost; TensorPtr mContextLengthDevice; TensorPtr mSeqLengthHost; TensorPtr mSeqLengthDevice; TensorPtr mMinLengthHost; TensorPtr mMinLengthDevice; TensorPtr mEndIdsHost; TensorPtr mEndIdsDevice; TensorPtr mBatchSlots; void subsetup(MinLengthPenaltyTestParams param) { mBatchSize = param.batchSize; mMaxBatchSize = 2 * mBatchSize; mVocabSize = param.vocabSize; mVocabSizePadded = padVocabSize(mVocabSize); mMaxInputLength = param.maxSeqLength; mSequenceLength = 2 * mMaxInputLength; // input + output mLogitsHost = mBufferManager->pinned(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mLogitsDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSizePadded}), std::is_same_v ? nvinfer1::DataType::kFLOAT : nvinfer1::DataType::kHALF); mPenaltyWorkspaceDevice = mBufferManager->gpu(ITensor::makeShape({mBatchSize, mVocabSize}), nvinfer1::DataType::kINT32); mSeqLengthHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mSeqLengthDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mContextLengthHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mContextLengthDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mMinLengthHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mMinLengthDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mEndIdsHost = mBufferManager->pinned(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mEndIdsDevice = mBufferManager->gpu(ITensor::makeShape({mMaxBatchSize}), nvinfer1::DataType::kINT32); mBatchSlots = mBufferManager->pinned(ITensor::makeShape({mBatchSize}), nvinfer1::DataType::kINT32); auto batchSlotsPtr = bufferCast(*mBatchSlots); for (SizeType bi = 0; bi < mBatchSize; ++bi) { batchSlotsPtr[bi] = 2 * bi; } initLogitsAndBias( bufferCast(*mLogitsHost), static_cast(nullptr), mBatchSize, mVocabSize, mVocabSizePadded); initRandomInt(bufferCast(*mContextLengthHost), mMaxBatchSize, 0, mMaxInputLength); initRandomInt(bufferCast(*mMinLengthHost), mMaxBatchSize, 1, mMaxInputLength); initRandomInt(bufferCast(*mEndIdsHost), mMaxBatchSize, 0, mVocabSize); auto seqLengthHostPtr = bufferCast(*mSeqLengthHost); auto contextLengthHostPtr = bufferCast(*mContextLengthHost); auto minLengthHostPtr = bufferCast(*mMinLengthHost); for (SizeType bi = 0; bi < mMaxBatchSize; bi++) { // Current generated seq len is randomly either smaller than min length or larger const auto generatedSeqLen = std::max(0, std::min( static_cast(minLengthHostPtr[bi] + 2 * std::pow(-1, std::rand() % 2)), mMaxInputLength)); seqLengthHostPtr[bi] = contextLengthHostPtr[bi] + generatedSeqLen; } mBufferManager->copy(*mLogitsHost, *mLogitsDevice); mBufferManager->copy(*mMinLengthHost, *mMinLengthDevice); mBufferManager->copy(*mContextLengthHost, *mContextLengthDevice); mBufferManager->copy(*mSeqLengthHost, *mSeqLengthDevice); mBufferManager->copy(*mEndIdsHost, *mEndIdsDevice); } void computeReference( T* logits, const int* minSeqLen, const int* endIds, const int* sequenceLengths, const int* contextLengths) { const bool IS_FP16 = std::is_same::value; const T MAX_T_VAL = (IS_FP16) ? 65504.F : FLT_MAX; auto batchSlotsPtr = bufferCast(*mBatchSlots); for (int32_t bi = 0; bi < mBatchSize; ++bi) { auto const batchSlot = batchSlotsPtr[bi]; const auto generatedSeqLen = sequenceLengths[batchSlot] - contextLengths[batchSlot]; const auto endId = endIds[batchSlot]; if (generatedSeqLen < minSeqLen[batchSlot]) { logits[bi * mVocabSizePadded + endId] = -MAX_T_VAL; } } } public: void runTest(MinLengthPenaltyTestParams param) { subsetup(param); InvokeBatchApplyPenaltyParams penalty_params{bufferCast(*mLogitsDevice), nullptr, bufferCast(*mPenaltyWorkspaceDevice), nullptr, nullptr, nullptr, nullptr, nullptr, false, static_cast(mBatchSize), 1, mSequenceLength, static_cast(mVocabSize), static_cast(mVocabSizePadded), nullptr, nullptr, bufferCast(*mContextLengthDevice), bufferCast(*mSeqLengthDevice), bufferCast(*mMinLengthDevice), bufferCast(*mEndIdsDevice), bufferCast(*mBatchSlots), mStream->get()}; tk::invokeBatchApplyPenalty(penalty_params); mStream->synchronize(); computeReference(bufferCast(*mLogitsHost), bufferCast(*mMinLengthHost), bufferCast(*mEndIdsHost), bufferCast(*mSeqLengthHost), bufferCast(*mContextLengthHost)); auto logitsOutHost = mBufferManager->copyFrom(*mLogitsDevice, MemoryType::kCPU); mStream->synchronize(); bool passed = checkResult(param.toString(), bufferCast(*logitsOutHost), bufferCast(*mLogitsHost), mBatchSize * mVocabSizePadded); EXPECT_TRUE(passed); } }; TYPED_TEST_SUITE(MinLengthPenaltyTest, FloatAndHalfTypes); TYPED_TEST(MinLengthPenaltyTest, BatchMaxSeqLen2) { this->runTest(MinLengthPenaltyTestParams().setBatchSize(16).setVocabSize(10).setMaxSeqLength(2)); } TYPED_TEST(MinLengthPenaltyTest, BatchMaxSeqLen64) { this->runTest(MinLengthPenaltyTestParams().setBatchSize(16).setVocabSize(51200).setMaxSeqLength(64)); } } // namespace