Je cherche à calculer l'entropie et les informations mutuelles un nombre énorme de fois dans le code critique de la performance. Comme étape intermédiaire, je dois compter le nombre d'occurrences de chaque valeur. Par exemple:
uint[] myArray = [1,1,2,1,4,5,2]; uint[] occurrences = countOccurrences(myArray); // Occurrences == [3, 2, 1, 1] or some permutation of that. // 3 occurrences of 1, 2 occurrences of 2, one each of 4 and 5.
3 Réponses :
Avec un tableau d'entiers, comme dans l'exemple, la manière la plus efficace serait d'avoir une matrice de Si vous ne pouvez pas faire cela, je ne peux pas penser à une meilleure alternative qu'un hashmap. Vous avez juste besoin d'avoir un algorithme de hachage rapide. Vous ne pouvez pas obtenir mieux que o (n) performances si vous souhaitez utiliser toutes vos données. Est-ce une option d'utiliser uniquement une partie des données que vous avez? P>
(Notez que le tri et le comptage sont asymptotiquement plus lentement (O (n * journal (n))) que l'utilisation d'une solution basée sur HASHMAP (O (N)).) P> int code> s et index qu'il basé sur vos valeurs (comme vous semblez le faire déjà). p>
Le tri est asymptotique plus lent, mais dans la situation d'entropie élevée (pas que de nombreuses occurrences de chaque valeur), il est plus rapide dans la pratique, même pour très grand n (dans les millions), car il est plus efficace de la cache.
Le hachage est généralement plus évolutif, car une autre réponse indique. Cependant, pour de nombreuses distributions possibles (et de nombreux cas réels de la vie réelle, où les compartiments sont souvent triés, en fonction de la manière dont la matrice globale a été assemblée), Timsort est souvent" de manière prénaturelle "(plus proche de O (n) que to O (n log n)) - j'entends qu'il est Va devenir probablement l'algorithme de tri standard / par défaut en Java à certaines données futures raisonnablement proches (son algorithme de tri standard en Python depuis des années). P>
Il n'y a pas de moyen probablement un moyen de résoudre ces problèmes, sauf au point de repère sur une sélection de cas représentatifs de la charge de travail réelle que vous prévoyez connaître (avec le risque évident que vous pouvez choisir un échantillon qui est arrivé à être biaisé / non représentatif - ce n'est pas un risque faible si vous essayez de créer une bibliothèque qui sera utilisée par de nombreux utilisateurs externes en dehors de votre contrôle). P>
Je ne savais pas sur Timsort code>, semble intéressant!
Veuillez raconter plus sur vos données.
Dans tous les cas, je suggère l'idée suivante: une fausse escorte modifiée pour compter les doublons. P>
C'est-à-dire que vous travaillez en termes de nombres, mais que des paires (nombre, fréquence) (vous pouvez utiliser une représentation intelligente efficace de la mémoire intelligente pour cela, par exemple deux tableaux au lieu d'une paire de paires, etc.) . p>
Vous commencez avec [(x1,1), (x2,1), ...] et faites une fusion comme d'habitude, mais lorsque vous fusionnez deux listes qui commencent avec la même valeur, vous mettez le valeur dans la liste de sortie avec leur somme de seventions. Sur votre exemple: p> ceci pourrait être considérablement amélioré en utilisant des astuces intelligentes pour effectuer une réduction initiale de la matrice (obtenir une gamme de valeur: des paires de présence beaucoup plus petite que l'original, mais la somme de «seary» pour chaque «valeur» est égale au nombre de survers de «valeur» dans le tableau d'origine). Par exemple, diviser le tableau en blocs continu où les valeurs ne diffèrent qu'au plus de 256 ou 65536 et utilisent un petit tableau pour compter des occurrences à l'intérieur de chaque bloc. En fait, cette astuce peut également être appliquée à des phases de fusion ultérieure. P> p>
Je ne peux pas penser à plus que ce que vous avez dit ci-dessus. Triez le tableau, puis passez-la séquentiellement en passe.
Peut-être que vous pourriez utiliser une sorte de hadoop ou de mapper / réduire pour accélérer votre algorithme? Autre que cela je ne vois rien.
@kgrad: J'utilise déjà pleinement tous mes noyaux en parallèle la boucle extérieure, il n'ya donc pas de point en parallèle une exécution individuelle de cette fonction.