2017-01-06 4 views
2

J'ai un fichier csv avec des noms proches de la ligne 845k.Optimisation pour la comparaison d'éléments HashMap lors de l'écriture

Je souhaite comparer une chaîne de noms floue. J'ai utilisé l'implémentation Java fuzzy string matching de l'algorithme fuzzywuzzy de Python.

Mis en œuvre sous le code, il fonctionne parfaitement pour moi. Le problème est le temps de traitement à beaucoup. Chaque ligne de comparaison de temps dure près de 15 secondes avec les autres lignes. Ceci est 240 lignes pour une heure et tout le processus sera près de 6000 lignes. Et tout le processus sera fini en mois. Ceci est un temps de travail inacceptable.

J'ai besoin d'une technique ou d'une méthode d'optimisation. J'ai besoin de suggestion plutôt que de solution.

Que conseillez-vous pour le code ci-dessous?

BufferedReader br = new BufferedReader(new FileReader("data/names.csv")); 
BufferedWriter bw = new BufferedWriter(new FileWriter("data/similars.csv")); 
ConcurrentHashMap<Integer,String> map = new ConcurrentHashMap<Integer,String>(); 

String lines; 
while((lines = br.readLine()) != null){ 
    String[] line = lines.split("\\t",-1); 
    Integer nameId = Integer.parseInt(line[0]); 
    String name = line[1]; 
    map.put(nameId, name); 
} 

for (Map.Entry<Integer, String> entry1 : map.entrySet()) { 
    Integer nameId1 = entry1.getKey(); 
    String name1 = entry1.getValue(); 

    for (Map.Entry<Integer, String> entry2 : map.entrySet()) { 
     Integer nameId2 = entry2.getKey(); 
     if (nameId1 == nameId2) { 
      continue; 
     } 
     String name2 = entry2.getValue(); 
     int ratio = FuzzySearch.ratio(name1,name2); 
     if(ratio > 95){ 
      bw.write(nameId1 + "," + nameId2 + "\n"); 
     } 
    } 
    // For to prevent matching same pairs again 
    map.remove(nameId1); 
} 
+1

Que diriez-vous juste courir ceci sur plusieurs CPU ou plusieurs serveurs dans AWS? Si j'ai raison, cela devrait prendre environ 3 jours sur 24 cœurs: ((845000 * 15/2)/60/60/24)/24 ~ 3.05 jours. Je pense que c'est acceptable parce que vous devriez le faire une fois. –

+0

@MaximDobryakov Il s'agit de mon pc de bureau avec i7 cpu et 16 gb ram.win 10 os. – Yilmazerhakan

Répondre

3
  1. Vous pouvez à la place Levenshtein algorithme à distance, peut-être vous donnera de meilleures performances. Ou essayez un autre algorithme. Fournir un lien vers Algoritm mise en œuvre
  2. Il est préférable de ne pas comparer avec Integer ==, utilisez nameId1.intValue() == nameId2
  3. Créer des threads N, où N est le nombre de cœurs. Mettez toutes vos lignes dans la file d'attente ConcurrentLinkedQueue. Laissez les threads interroger la file d'attente, prendre un mot, faire de la compassion, une fois terminé - écrire dans le fichier sous la section synchronisée. Cela vous permettra d'utiliser tous vos cœurs sur votre PC, pas seulement 1
  4. Pourquoi cela prend autant de temps, peut-être que vous avez des restrictions de mémoire, ce qui oblige le GC à manger les cycles de votre processeur et à affecter les performances.
  5. Vous pouvez appliquer une optimisation mineure, disons que si elle est différente entre la longueur des mots est plus de 50%, vous ne serez jamais match de 95%
  6. Jetez un oeil à ce implementation ils utilisent la valeur de seuil, je crois qu'il donnera Je pense que l'algoritm reviendra plus tôt si la distance est supérieure au seuil. Vérifiez également ce question
+0

J'utiliserais plus de threads que de cœurs, car deux threads peuvent toujours tourner sur le même core. – NickL

+0

Merci Anton. Je vais essayer 2 et 5 rapidement. Pour 1, j'ai édité et lié la bibliothèque de github de fuzzywuzzy. Il a également basé sur levensthein et a quelques variétés comme des mots hors de comparaison. Je ne pouvais pas comprendre 2ème. désolé, j'utilise rarement java mais NameIds aussi entier. Je vais rechercher, apprendre et essayer 3. Pour 4 c'est mon bureau et a donné des propriétés dans les commentaires de la réponse ci-dessus. – Yilmazerhakan

+0

2) est à propos de ce que vous ne devriez pas comparer les objets avec ==, en appelant intValue() sur l'objet Integer, vous comparez les primitives. Cependant, dans ce cas, parce que nous parlons de la clé d'un hashmap, je pense qu'il est sûr (et même le plus rapide peut-être?) D'utiliser == sur les objets Integer. – NickL