| 249 | |
| 250 | template <typename TScoreCalcMapper, typename TGetScore> |
| 251 | void MapGenericCalcScore( |
| 252 | TGetScore getScore, |
| 253 | double scoreStDev, |
| 254 | TCandidatesContext* candidatesContext, |
| 255 | TLearnContext* ctx) { |
| 256 | |
| 257 | Y_ASSERT(ctx->Params.SystemOptions->IsMaster()); |
| 258 | |
| 259 | auto scoreDistribution = GetScoreDistribution(ctx->Params.ObliviousTreeOptions->RandomScoreType); |
| 260 | |
| 261 | auto& candidateList = candidatesContext->CandidateList; |
| 262 | |
| 263 | const int workerCount = TMasterEnvironment::GetRef().RootEnvironment->GetSlaveCount(); |
| 264 | auto allStatsFromAllWorkers = ApplyMapper<TScoreCalcMapper>( |
| 265 | workerCount, |
| 266 | TMasterEnvironment::GetRef().SharedTrainData, |
| 267 | candidateList); |
| 268 | |
| 269 | // some workers may return empty result because they don't have any learn subset |
| 270 | const TVector<size_t> validWorkers = GetNonEmptyElementsIndices(allStatsFromAllWorkers); |
| 271 | auto validWorkersSize = validWorkers.size(); |
| 272 | CB_ENSURE_INTERNAL(validWorkersSize, "No workers returned score stats"); |
| 273 | |
| 274 | const int candidateCount = candidateList.ysize(); |
| 275 | const ui64 randSeed = ctx->LearnProgress->Rand.GenRand(); |
| 276 | // set best split for each candidate |
| 277 | NPar::ParallelFor( |
| 278 | *ctx->LocalExecutor, |
| 279 | 0, |
| 280 | candidateCount, |
| 281 | [&] (int candidateIdx) { |
| 282 | auto& subCandidates = candidateList[candidateIdx].Candidates; |
| 283 | const int subcandidateCount = subCandidates.ysize(); |
| 284 | TVector<TVector<double>> allScores(subcandidateCount); |
| 285 | for (int subcandidateIdx = 0; subcandidateIdx < subcandidateCount; ++subcandidateIdx) { |
| 286 | // reduce across workers |
| 287 | auto& reducedStats = allStatsFromAllWorkers[validWorkers[0]][candidateIdx][subcandidateIdx]; |
| 288 | for (size_t validWorkerIdx = 1; validWorkerIdx < validWorkersSize; ++validWorkerIdx) { |
| 289 | const auto& stats = allStatsFromAllWorkers[validWorkers[validWorkerIdx]][candidateIdx][subcandidateIdx]; |
| 290 | reducedStats.Add(stats); |
| 291 | } |
| 292 | const auto& splitInfo = subCandidates[subcandidateIdx]; |
| 293 | allScores[subcandidateIdx] = getScore(reducedStats, splitInfo); |
| 294 | } |
| 295 | SetBestScore( |
| 296 | randSeed + candidateIdx, |
| 297 | allScores, |
| 298 | scoreDistribution, |
| 299 | scoreStDev, |
| 300 | *candidatesContext, |
| 301 | &subCandidates); |
| 302 | }); |
| 303 | } |
| 304 | |
| 305 | // TODO(espetrov): Remove unused code. |
| 306 | void MapCalcScore( |
nothing calls this directly
no test coverage detected