From 8fe164e46b39df2a77063e742934f32d897bf6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Boull=C3=A9?= Date: Thu, 23 Nov 2023 14:49:18 +0100 Subject: [PATCH] Improve management of too many unique values in huge datasets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cf. issue Fix bug for descriptive stats with huge dataset (400 Gb) #90 - corrige dans la V10.2 et reporte dans la V11 - amelioration supplementaire dans la V11 uniquement - amelioration du dimensionnement de la tache de preparation univariée - KWDataPreparationTask::ComputeNecessaryUnivariateStatsMemory - prise en compte si necessaire d'au moins la place de un Symbol et une valeur sparse par record - vérification de la protection contre plus de deux milliard d'instances - gere dans KWDatabaseBasicStatsTask - erreur diagnostiquee dans KWClassStats::ComputeStats - ajout d'un warning si trop d'instances - limite a 10000000 definie dans KWClassStats::GetLargeDatabaseSize - warning dans KWClassStats::ComputeStats - ajout d'une protection contre le depassement de deux milliards de Symbol lors de la lecture de la base - gerer dans KWDataTableSlice::PhysicalReadObject Correction additionnelle - KWDRTableSortCompareObjects: ajout de la prise en compte du type Text pour les champs triables --- .../KWDRRuleLibrary/KWDRMultiTable.cpp | 3 ++ .../KWData/KWDataTableDriverTextFile.cpp | 31 ++++++------ .../KWData/KWDataTableDriverTextFile.h | 2 +- src/Learning/KWData/KWSymbol.cpp | 9 +--- src/Learning/KWData/KWSymbol.h | 11 +++-- .../KWDataPreparation/KWClassStats.cpp | 11 +++++ src/Learning/KWDataPreparation/KWClassStats.h | 3 ++ .../KWDataPreparationTask.cpp | 47 +++++++++++-------- .../KWDataPreparationUnivariateTask.cpp | 4 +- .../KWDataPreparationUnivariateTask.h | 2 +- .../KWDataUtils/KWDataTableSliceSet.cpp | 23 +++++++-- .../KWDataUtils/KWDataTableSliceSet.h | 2 +- .../KWModeling/KWPredictorDataGrid.cpp | 10 ++-- 13 files changed, 99 insertions(+), 59 deletions(-) diff --git a/src/Learning/KWDRRuleLibrary/KWDRMultiTable.cpp b/src/Learning/KWDRRuleLibrary/KWDRMultiTable.cpp index 70985dd72..1cf5b8ae1 100644 --- a/src/Learning/KWDRRuleLibrary/KWDRMultiTable.cpp +++ b/src/Learning/KWDRRuleLibrary/KWDRMultiTable.cpp @@ -1853,6 +1853,9 @@ int KWDRTableSortCompareObjects(const void* elem1, const void* elem2) nDiff = sortOperand->GetTimestampTZValue(object1).Compare( sortOperand->GetTimestampTZValue(object2)); break; + case KWType::Text: + nDiff = sortOperand->GetTextValue(object1).CompareValue(sortOperand->GetTextValue(object2)); + break; default: nDiff = 0; assert(false); diff --git a/src/Learning/KWData/KWDataTableDriverTextFile.cpp b/src/Learning/KWData/KWDataTableDriverTextFile.cpp index 18bfbf66b..ae96822f0 100644 --- a/src/Learning/KWData/KWDataTableDriverTextFile.cpp +++ b/src/Learning/KWData/KWDataTableDriverTextFile.cpp @@ -752,7 +752,7 @@ longint KWDataTableDriverTextFile::GetEstimatedObjectNumber() lHeaderLigneSize = temporaryFile.GetPositionInFile(); // Calcul du nombre de lignes hors ligne d'entete - lLineNumber = temporaryFile.GetBufferLineNumber() - 1; + lLineNumber = (longint)temporaryFile.GetBufferLineNumber() - 1; // Calcul de la taille correspondante occupee dans le fichier lTotalLineSize = temporaryFile.GetCurrentBufferSize() - lHeaderLigneSize; @@ -1026,7 +1026,7 @@ longint KWDataTableDriverTextFile::GetUsedMemory() const return lUsedMemory; } -longint KWDataTableDriverTextFile::GetInMemoryEstimatedObjectNumber(longint lInputFileSize) +longint KWDataTableDriverTextFile::GetInMemoryEstimatedObjectNumber(longint lInputFileSize) const { boolean bDisplay = false; longint lEstimatedObjectNumber; @@ -1113,14 +1113,14 @@ longint KWDataTableDriverTextFile::GetEstimatedUsedInputDiskSpacePerObject() con // Estimation de la taille d'un objet natif lNativeObjectSize = nMinRecordSize; // Fin de ligne plus un minimum lNativeObjectSize += - nDenseNativeValueNumber * nDenseValueSize; // Valeurs dense de l'objet (valeur + separateur) + (longint)nDenseNativeValueNumber * nDenseValueSize; // Valeurs dense de l'objet (valeur + separateur) lNativeObjectSize += - nTextNativeValueNumber * + (longint)nTextNativeValueNumber * nTextValueSize; // Longueur moyenne d'un champ texte (entre un ancien et un nouveau tweet...) - lNativeObjectSize += nSparseNativeValueNumber * + lNativeObjectSize += (longint)nSparseNativeValueNumber * nSparseValueSize; // Valeurs sparse de l'objet (cle + ':' + valeur + blanc + separateur) lNativeObjectSize += - GetClass()->GetKeyAttributeNumber() * nKeyFieldSize; // Taille des champs de la cle (heuristique) + (longint)GetClass()->GetKeyAttributeNumber() * nKeyFieldSize; // Taille des champs de la cle (heuristique) // Affichage if (bDisplay) @@ -1197,12 +1197,13 @@ longint KWDataTableDriverTextFile::GetEstimatedUsedMemoryPerObject() const // Estimation de la memoire necessaire pour stocker un objet lObjectSize = sizeof(KWObject) + 2 * sizeof(void*); // KWObject a vide lObjectSize += - nPhysicalDenseLoadedValueNumber * (sizeof(KWValue) + nDenseValueSize); // Valeurs dense de l'objet - lObjectSize += nPhysicalTextLoadedValueNumber * nTextValueSize; // Valeurs Text de l'objet - lObjectSize += nPhysicalSparseLoadedValueNumber * (sizeof(int) + sizeof(KWValue)); // Valeurs sparse de l'objet - lObjectSize += nPhysicalSparseLoadedValueBlockNumber * sizeof(KWSymbolValueBlock); + nPhysicalDenseLoadedValueNumber * (sizeof(KWValue) + nDenseValueSize); // Valeurs dense de l'objet + lObjectSize += (longint)nPhysicalTextLoadedValueNumber * nTextValueSize; // Valeurs Text de l'objet lObjectSize += - GetClass()->GetKeyAttributeNumber() * + (longint)nPhysicalSparseLoadedValueNumber * (sizeof(int) + sizeof(KWValue)); // Valeurs sparse de l'objet + lObjectSize += (longint)nPhysicalSparseLoadedValueBlockNumber * sizeof(KWSymbolValueBlock); + lObjectSize += + (longint)GetClass()->GetKeyAttributeNumber() * (Symbol::GetUsedMemoryPerSymbol() + nKeyFieldSize); // Taille des Symbol de la cle (sans leur contenu) // Affichage @@ -1279,10 +1280,10 @@ longint KWDataTableDriverTextFile::GetEstimatedUsedOutputDiskSpacePerObject(cons // Estimation de la memoire necessaire pour stocker un objet a ecrire // (generalisation de l'objet natif) lWrittenObjectSize = nMinRecordSize; - lWrittenObjectSize += nDenseLoadedValueNumber * nDenseValueSize; - lWrittenObjectSize += nTextLoadedValueNumber * nTextValueSize; - lWrittenObjectSize += nSparseLoadedValueNumber * nSparseValueSize; - lWrittenObjectSize += kwcLogicalClass->GetKeyAttributeNumber() * nKeyFieldSize; + lWrittenObjectSize += (longint)nDenseLoadedValueNumber * nDenseValueSize; + lWrittenObjectSize += (longint)nTextLoadedValueNumber * nTextValueSize; + lWrittenObjectSize += (longint)nSparseLoadedValueNumber * nSparseValueSize; + lWrittenObjectSize += (longint)kwcLogicalClass->GetKeyAttributeNumber() * nKeyFieldSize; // Affichage if (bDisplay) diff --git a/src/Learning/KWData/KWDataTableDriverTextFile.h b/src/Learning/KWData/KWDataTableDriverTextFile.h index c73dfae64..144161980 100644 --- a/src/Learning/KWData/KWDataTableDriverTextFile.h +++ b/src/Learning/KWData/KWDataTableDriverTextFile.h @@ -77,7 +77,7 @@ class KWDataTableDriverTextFile : public KWDataTableDriver // Variante de l'estimation du nombre d'objets dans la base, en memoire et sans acces disque, // en analysant la structure du dictionnaire avec dimensionnement heuristique - longint GetInMemoryEstimatedObjectNumber(longint lInputFileSize); + longint GetInMemoryEstimatedObjectNumber(longint lInputFileSize) const; // Estimation heuristique de la place disque par record d'un fichier a lire en se basant sur les variable native // du dictionnaire diff --git a/src/Learning/KWData/KWSymbol.cpp b/src/Learning/KWData/KWSymbol.cpp index 90dd5ace9..195ffbdc8 100644 --- a/src/Learning/KWData/KWSymbol.cpp +++ b/src/Learning/KWData/KWSymbol.cpp @@ -37,13 +37,6 @@ Symbol Symbol::BuildNewSymbol(const char* sBaseName) return Symbol(sNewSymbol); } -int Symbol::GetSymbolNumber() -{ - int nSymbolNumber; - nSymbolNumber = sdSharedSymbols.GetCount(); - return nSymbolNumber; -} - longint Symbol::GetAllSymbolsUsedMemory() { longint lUsedMemory; @@ -512,7 +505,7 @@ inline KWSymbolData* KWSymbolData::NewSymbolData(const char* sValue, int nLength pSymbolData->nLength = nLength; // Recopie de la chaine de caracteres ('\0' en fin de chaine) - memcpy(&(pSymbolData->cFirstStringChar), sValue, nLength + 1); + memcpy(&(pSymbolData->cFirstStringChar), sValue, (longint)nLength + 1); return pSymbolData; } diff --git a/src/Learning/KWData/KWSymbol.h b/src/Learning/KWData/KWSymbol.h index 007233d8d..d66c91896 100644 --- a/src/Learning/KWData/KWSymbol.h +++ b/src/Learning/KWData/KWSymbol.h @@ -331,17 +331,17 @@ class KWSymbolData : public SystemObject //// Implementation protected: // Longueur de la chaine de caracteres - inline int GetLength() + inline int GetLength() const { return nLength; } // Acces a la valeur chaine de caracteres - inline char* GetString() + inline const char* GetString() const { return cFirstStringChar; } - inline char GetAt(int nIndex) + inline char GetAt(int nIndex) const { return cFirstStringChar[nIndex]; } @@ -645,6 +645,11 @@ inline void Symbol::Reset() symbolData = NULL; } +inline int Symbol::GetSymbolNumber() +{ + return sdSharedSymbols.GetCount(); +} + #ifdef __C11__ inline Symbol::Symbol(Symbol&& sSymbol) noexcept { diff --git a/src/Learning/KWDataPreparation/KWClassStats.cpp b/src/Learning/KWDataPreparation/KWClassStats.cpp index a7240981c..f6a48ab9d 100644 --- a/src/Learning/KWDataPreparation/KWClassStats.cpp +++ b/src/Learning/KWDataPreparation/KWClassStats.cpp @@ -129,6 +129,12 @@ boolean KWClassStats::ComputeStats() LongintToReadableString(lCollectedObjectNumber) + ")"); bOk = false; } + // Warning si nombre tres important d'instances + if (bOk and lCollectedObjectNumber >= GetLargeDatabaseSize()) + { + AddWarning(sTmp + "The train dataset contains many instances (" + + LongintToReadableString(lCollectedObjectNumber) + ")"); + } // Calcul des statistiques de l'attribut cible (ou du nombre d'instances a traiter en non supervise) bOk = bOk and not TaskProgression::IsInterruptionRequested(); @@ -1472,6 +1478,11 @@ int KWClassStats::GetTargetValueLargeNumber(int nDatabaseSize) return 10 + (int)sqrt(1.0 * nDatabaseSize); } +int KWClassStats::GetLargeDatabaseSize() +{ + return 10000000; +} + boolean KWClassStats::CheckConstructionAttributes(const ObjectDictionary* odConstructedAttributes) const { boolean bOk = true; diff --git a/src/Learning/KWDataPreparation/KWClassStats.h b/src/Learning/KWDataPreparation/KWClassStats.h index 8d019603f..c62942234 100644 --- a/src/Learning/KWDataPreparation/KWClassStats.h +++ b/src/Learning/KWDataPreparation/KWClassStats.h @@ -330,6 +330,9 @@ class KWClassStats : public KWLearningReport // Nombre de valeurs cibles dans le cas categoriel, considere comme important virtual int GetTargetValueLargeNumber(int nDatabaseSize); + // Taille de base consideree comme important + int GetLargeDatabaseSize(); + // Verification de la specification d'un ensmeble de variable de construction boolean CheckConstructionAttributes(const ObjectDictionary* odConstructedAttributes) const; diff --git a/src/Learning/KWDataPreparation/KWDataPreparationTask.cpp b/src/Learning/KWDataPreparation/KWDataPreparationTask.cpp index 580ce7670..9aa8aa629 100644 --- a/src/Learning/KWDataPreparation/KWDataPreparationTask.cpp +++ b/src/Learning/KWDataPreparation/KWDataPreparationTask.cpp @@ -181,7 +181,8 @@ int KWDataPreparationTask::ComputeMaxLoadableAttributeNumber(const KWLearningSpe // esclaves en les faisant travailler plusieurs fois chacun, de facon a minimer l'attente du dernier // esclave if (lMaxAttributeNumber * nMaxProcessBySlave * nSlaveNumber > nUsedAttributeNumber) - lMaxAttributeNumber = 1 + nUsedAttributeNumber / (nSlaveNumber * nMaxProcessBySlave); + lMaxAttributeNumber = + 1 + (longint)nUsedAttributeNumber / ((longint)nSlaveNumber * nMaxProcessBySlave); // On ajuste le nombre d'attribut pour qu'il soit si possible equilibre par process esclave nMaxAttributeNumber = (int)lMaxAttributeNumber; @@ -351,10 +352,10 @@ longint KWDataPreparationTask::ComputeNecessaryUnivariateStatsMemory(const KWLea // L'estimation est tres approximative, et est consideree comme raisonnable que ce soit dans le cas supervise // ou non supervise, meme avec des histogrammes lAttributeStatSize += - nMeanValueNumber * lSymbolSize + sizeof(KWAttributeStats) + sizeof(KWDescriptiveContinuousStats) + + (longint)nMeanValueNumber * lSymbolSize + sizeof(KWAttributeStats) + sizeof(KWDescriptiveContinuousStats) + sizeof(KWDataGridStats) + 2 * (sizeof(KWDGSAttributeGrouping) + KWClass::GetNameMaxLength()) + - (nMeanPartNumber + nMeanValueNumber + nTargetModalityNumber) * (sizeof(KWValue) + sizeof(int)) + - nMeanPartNumber * nTargetModalityNumber * sizeof(int); + (longint)(nMeanPartNumber + nMeanValueNumber + nTargetModalityNumber) * (sizeof(KWValue) + sizeof(int)) + + (longint)nMeanPartNumber * nTargetModalityNumber * sizeof(int); return lAttributeStatSize; } @@ -389,11 +390,11 @@ longint KWDataPreparationTask::ComputeNecessaryBivariateStatsMemory(const KWLear nTargetModalityNumber = nMeanPartNumber; // Taille occupee par une paire d'attribut - lAttributePairStatSize = - lAttributeBaseStatSize + nMeanValueNumber * lSymbolSize + sizeof(KWDataGridStats) + - 3 * (sizeof(KWDGSAttributeGrouping) + KWClass::GetNameMaxLength()) + - (2 * nMeanPartNumber + 2 * nMeanValueNumber + nTargetModalityNumber) * (sizeof(KWValue) + sizeof(int)) + - nMeanPartNumber * nMeanPartNumber * nTargetModalityNumber * sizeof(int); + lAttributePairStatSize = lAttributeBaseStatSize + nMeanValueNumber * lSymbolSize + sizeof(KWDataGridStats) + + 3 * (sizeof(KWDGSAttributeGrouping) + KWClass::GetNameMaxLength()) + + (longint)(2 * nMeanPartNumber + 2 * nMeanValueNumber + nTargetModalityNumber) * + (sizeof(KWValue) + sizeof(int)) + + (longint)nMeanPartNumber * nMeanPartNumber * nTargetModalityNumber * sizeof(int); return lAttributePairStatSize; } @@ -487,15 +488,23 @@ longint KWDataPreparationTask::ComputeNecessaryWorkingMemory(const KWLearningSpe kwcClass = learningSpec->GetClass(); check(kwcClass); - // Calcul de la taille a vide d'un objet (avec au minimum un champs, en prenant en compte le cas sparse) + // Calcul de la taille a vide d'un objet + // On compate au minimum un champs, en prenant en compte le cas sparse + // et un eventuel attribut Symbol ayant autant de valeurs que d'instances lEmptyObjectSize = sizeof(KWObject) + sizeof(KWObject*) + sizeof(KWValue*) + GetNecessaryMemoryPerDenseValue(); + if (kwcClass->GetLoadedAttributeBlockNumber() > 0) + lEmptyObjectSize += GetNecessaryMemoryPerEmptyValueBlock(); + if (kwcClass->GetUsedDenseAttributeNumberForType(KWType::Symbol) + + kwcClass->GetUsedDenseAttributeNumberForType(KWType::Text) > + 0) + lEmptyObjectSize += Symbol::GetUsedMemoryPerSymbol(); // Prise en compte d'un dictionnaire et d'une base minimale lClassAttributeMemorySize = ComputeNecessaryClassAttributeMemory(); lWorkingMemorySize += dummyClass.GetUsedMemory(); lWorkingMemorySize += lClassAttributeMemorySize; lWorkingMemorySize += dummyDatabase.GetUsedMemory(); - lWorkingMemorySize += 2 * KWClass::GetNameMaxLength(); + lWorkingMemorySize += 2 * (longint)KWClass::GetNameMaxLength(); // Taille de la base chargee en memoire avec deux champs dont un categoriel // On a ainsi une petite marge pour un dimensionnement minimal @@ -570,14 +579,14 @@ longint KWDataPreparationTask::ComputeNecessaryWorkingMemory(const KWLearningSpe // Un grille bivariee maximale complete initiale (cf. KWAttributeSubsetStats.CreateDatagrid) lInitialDatagridSize = - nDatabaseObjectNumber * sizeof(KWDGMCell) + - (nSourceValueNumber + nTargetValueNumber) * + (longint)nDatabaseObjectNumber * sizeof(KWDGMCell) + + (longint)(nSourceValueNumber + nTargetValueNumber) * (sizeof(KWDGMPart) + max(sizeof(KWDGInterval), sizeof(KWDGValueSet) + sizeof(KWDGValue))); lWorkingMemorySize += lInitialDatagridSize; // Plus une grille univariee pour la post-optimisation (cf. // KWDataGridPostOptimizer::BuildUnivariateInitialDataGrid) - lInitialUnivariateDatagridSize = (int)ceil(sqrt(nDatabaseObjectNumber * 1.0)) * + lInitialUnivariateDatagridSize = (longint)ceil(sqrt(nDatabaseObjectNumber * 1.0)) * (sizeof(KWDGMCell) + sizeof(KWDGMPart) + max(sizeof(KWDGInterval), sizeof(KWDGValueSet) + sizeof(KWDGValue))); lWorkingMemorySize += lInitialUnivariateDatagridSize; @@ -585,8 +594,8 @@ longint KWDataPreparationTask::ComputeNecessaryWorkingMemory(const KWLearningSpe // Plus deux grilles reduites de travail (cf. VNSOptimizer) lWorkingDatagridSize = nDatabaseObjectNumber * (sizeof(KWDGMCell) + 2 * sizeof(KWDGValue)) + - (int)ceil(sqrt(nDatabaseObjectNumber * 1.0) + - min(nTargetValueNumber * 1.0, sqrt(nDatabaseObjectNumber * 1.0))) * + (longint)ceil(sqrt(nDatabaseObjectNumber * 1.0) + + min(nTargetValueNumber * 1.0, sqrt(nDatabaseObjectNumber * 1.0))) * (sizeof(KWDGMPart) + max(sizeof(KWDGInterval), sizeof(KWDGValueSet) + sizeof(KWDGValue))); lWorkingMemorySize += 2 * lWorkingDatagridSize; @@ -910,10 +919,10 @@ longint KWDataPreparationTask::ComputeDatabaseMinimumAllValuesMemory(int nDenseS require(nObjectNumber >= 0); // Memoire pour les valeurs des attributs dense - lDatabaseAllValuesMemory = (nDenseSymbolAttributeNumber + nDenseContinuousAttributeNumber) * + lDatabaseAllValuesMemory = (longint)(nDenseSymbolAttributeNumber + nDenseContinuousAttributeNumber) * GetNecessaryMemoryPerDenseValue() * nObjectNumber; - // Prise uen compte d'un overhead en cas d'attributs d'ense Symbol + // Prise en compte d'un overhead en cas d'attributs d'ense Symbol if (nDenseSymbolAttributeNumber > 0) lDatabaseAllValuesMemory += ComputeEstimatedAttributeSymbolValuesMemory( nObjectNumber * GetExpectedMeanSymbolValueLength(), nObjectNumber); @@ -990,7 +999,7 @@ longint KWDataPreparationTask::GetNecessaryMemoryPerSparseValue() const longint KWDataPreparationTask::GetExpectedMeanSymbolValueLength() const { - // On se base arbitrairement su une longueur moyenne egale a celle d'un champ + // On se base arbitrairement sur une longueur moyenne egale a celle d'un champ return sizeof(KWValue); } diff --git a/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.cpp b/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.cpp index 4c27dbfe7..5168e4e9f 100644 --- a/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.cpp +++ b/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.cpp @@ -791,7 +791,7 @@ boolean KWDataPreparationUnivariateTask::SlaveProcess() // la memoire minimum demandee lAvailableWorkingMemory = shared_lLargestSliceUsedMemory - lSliceUsedMemory + - +(shared_nLargestSliceAttributeNumber - slice->GetClass()->GetLoadedAttributeNumber()) * + +(shared_nLargestSliceAttributeNumber - (longint)slice->GetClass()->GetLoadedAttributeNumber()) * lNecessaryUnivariateStatsMemory + shared_lLargestSliceMaxBlockWorkingMemory + shared_lLargestSliceDatabaseAllValuesMemory; @@ -934,7 +934,7 @@ void KWDataPreparationUnivariateTask::InitializeSliceLexicographicSortCriterion( require(masterDataTableSliceSet != NULL); // Premier critere: nombre total de valeurs, dense plus sparse - slice->GetLexicographicSortCriterion()->Add(double(slice->GetClass()->GetLoadedDenseAttributeNumber() * + slice->GetLexicographicSortCriterion()->Add(double((longint)slice->GetClass()->GetLoadedDenseAttributeNumber() * masterDataTableSliceSet->GetTotalInstanceNumber() + slice->GetTotalAttributeBlockValueNumber())); diff --git a/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.h b/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.h index bc3e809ac..6f6392424 100644 --- a/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.h +++ b/src/Learning/KWDataPreparation/KWDataPreparationUnivariateTask.h @@ -179,7 +179,7 @@ class KWDataPreparationUnivariateTask : public KWDataPreparationTask // Sortie: // . ivUsedAttributeStepIndexes: pour chaque attribut, index de l'etape de chargement (-1 si attribut en // Unused) - // Retourne le nombre de partie de la partition + // Retourne le nombre de parties de la partition int ComputeSlicePartition(KWDataTableSlice* slice, int nObjectNumber, longint lAvailableWorkingMemory, IntVector* ivUsedAttributePartIndexes); diff --git a/src/Learning/KWDataUtils/KWDataTableSliceSet.cpp b/src/Learning/KWDataUtils/KWDataTableSliceSet.cpp index 30f70619c..f87200aa1 100644 --- a/src/Learning/KWDataUtils/KWDataTableSliceSet.cpp +++ b/src/Learning/KWDataUtils/KWDataTableSliceSet.cpp @@ -1381,7 +1381,7 @@ boolean KWDataTableSliceSet::ReadAllObjectsWithClass(const KWClass* kwcInputClas } KWClass* KWDataTableSliceSet::BuildClassFromAttributeNames(const ALString& sInputClassName, - const StringVector* svInputAttributeNames) + const StringVector* svInputAttributeNames) const { KWClass* kwcNewClass; ObjectDictionary odSliceAttributes; @@ -3179,15 +3179,15 @@ boolean KWDataTableSlice::ReadAll() Global::DesactivateErrorFlowControl(); // Test si interruption sans qu'il y ait d'erreur - if (IsError() or TaskProgression::IsInterruptionRequested()) + if (not bOk or IsError() or TaskProgression::IsInterruptionRequested()) { bOk = false; // Warning ou erreur selon le cas - if (IsError()) - AddError("Read data table slice interrupted because of errors"); - else + if (TaskProgression::IsInterruptionRequested()) AddWarning("Read data table slice interrupted by user"); + else + AddError("Read data table slice interrupted because of errors"); } // Fermeture @@ -3592,6 +3592,7 @@ boolean KWDataTableSlice::PhysicalOpenForRead(KWClass* driverClass, boolean bOpe boolean KWDataTableSlice::PhysicalReadObject(KWObject*& kwoObject, boolean bCreate) { boolean bOk = true; + const int nMaxSymbolNumber = 2000000000; ALString sTmp; require(IsOpenedForRead()); @@ -3635,6 +3636,18 @@ boolean KWDataTableSlice::PhysicalReadObject(KWObject*& kwoObject, boolean bCrea LongintToString(read_SliceDataTableDriver->GetRecordIndex()) + " (slice " + FileService::GetURIUserLabel(svDataFileNames.GetAt(read_nDataFileIndex)) + ")"); } + + // Arret si trop de valeurs unique dans les Symbol avec risque de depassement de la capacite + // des dictionnaires de Symbol + if (bOk and Symbol::GetSymbolNumber() > nMaxSymbolNumber) + { + bOk = false; + AddError(sTmp + "Read slice file interrupted " + + "because of too many unique categorical values in the data (beyond " + + LongintToReadableString(nMaxSymbolNumber) + "), after line " + + LongintToString(read_SliceDataTableDriver->GetRecordIndex()) + " (slice " + + FileService::GetURIUserLabel(svDataFileNames.GetAt(read_nDataFileIndex)) + ")"); + } } // Fermeture si necessaire du fichier courant diff --git a/src/Learning/KWDataUtils/KWDataTableSliceSet.h b/src/Learning/KWDataUtils/KWDataTableSliceSet.h index 1701a14ec..c7cfa42f1 100644 --- a/src/Learning/KWDataUtils/KWDataTableSliceSet.h +++ b/src/Learning/KWDataUtils/KWDataTableSliceSet.h @@ -232,7 +232,7 @@ class KWDataTableSliceSet : public Object // a vis des noms, types, et blocs d'attributs, et son nom sera specifie dans l'appele // Memoire: la classe construite en retour appartient a l'appelant KWClass* BuildClassFromAttributeNames(const ALString& sInputClassName, - const StringVector* svInputAttributeNames); + const StringVector* svInputAttributeNames) const; // Acces au tableau des tranches // Memoire: le tableau et son contenu appartiennent a l'appelant, mais peuvent etre modifies sous la diff --git a/src/Learning/KWModeling/KWPredictorDataGrid.cpp b/src/Learning/KWModeling/KWPredictorDataGrid.cpp index c60f8bf22..d7d23899a 100644 --- a/src/Learning/KWModeling/KWPredictorDataGrid.cpp +++ b/src/Learning/KWModeling/KWPredictorDataGrid.cpp @@ -454,8 +454,8 @@ ObjectArray* KWPredictorDataGrid::SelectTrainAttributeStats() // Initialisation de la memoire necessaire pour l'apprentissage lEmptyObjectSize = sizeof(KWObject) + sizeof(KWObject*); lUsedMemory = lEmptyExeSize + GetClassStats()->GetInstanceNumber() * (lEmptyObjectSize + sizeof(KWValue)); - lUsedMemory += - 3 * GetClassStats()->GetInstanceNumber() * (sizeof(KWDGMCell) + nTargetModalityNumber * sizeof(KWValue)); + lUsedMemory += 3 * (longint)GetClassStats()->GetInstanceNumber() * + (sizeof(KWDGMCell) + nTargetModalityNumber * sizeof(KWValue)); // On compte le nombre d'attributs utilisables pour l'apprentissage nUsedAttributes = 0; @@ -468,14 +468,16 @@ ObjectArray* KWPredictorDataGrid::SelectTrainAttributeStats() if (attributeStats->GetAttributeType() == KWType::Continuous) { lAttributeRequiredMemory = GetClassStats()->GetInstanceNumber() * sizeof(KWValue); - lAttributeRequiredMemory += 3 * attributeStats->GetDescriptiveStats()->GetValueNumber() * + lAttributeRequiredMemory += 3 * + (longint)attributeStats->GetDescriptiveStats()->GetValueNumber() * (sizeof(KWDGMPart) + sizeof(KWDGInterval)); } // et dans le cas symbolique else { lAttributeRequiredMemory = GetClassStats()->GetInstanceNumber() * sizeof(KWValue); - lAttributeRequiredMemory += 3 * attributeStats->GetDescriptiveStats()->GetValueNumber() * + lAttributeRequiredMemory += 3 * + (longint)attributeStats->GetDescriptiveStats()->GetValueNumber() * (sizeof(KWDGMPart) + sizeof(KWDGValueSet) + sizeof(KWDGValue)); }