Implementé el paradigma MapReduce basado en local clustering coefficient algorithm. Sin embargo, me he encontrado con problemas serios para conjuntos de datos más grandes o conjuntos de datos específicos (alto grado promedio de un nodo). Traté de ajustar mi plataforma hadoop y el código, sin embargo, los resultados fueron insatisfactorios (por decir lo menos). No, he vuelto mi atención para realmente cambiar/mejorar el algoritmo. A continuación es mi actual algoritmo (pseudo código)Algoritmo del coeficiente de agrupamiento local distribuido (MapReduce/Hadoop)
foreach(Node in Graph) {
//Job1
/* Transform edge-based input dataset to node-based dataset */
//Job2
map() {
emit(this.Node, this.Node.neighbours) //emit myself data to all my neighbours
emit(this.Node, this.Node) //emit myself to myself
}
reduce() {
NodeNeighbourhood nodeNeighbourhood;
while(values.hasNext) {
if(myself)
this.nodeNeighbourhood.setCentralNode(values.next) //store myself data
else
this.nodeNeighbourhood.addNeighbour(values.next) //store neighbour data
}
emit(null, this.nodeNeighbourhood)
}
//Job3
map() {
float lcc = calculateLocalCC(this.nodeNeighbourhood)
emit(0, lcc) //emit all lcc to specific key, combiners are used
}
reduce() {
float combinedLCC;
int numberOfNodes;
while(values.hasNext) {
combinedLCC += values.next;
}
emit(null, combinedLCC/numberOfNodes); // store graph average local clustering coefficient
}
}
poco más detalles sobre el código. Para los gráficos dirigidos, los datos vecinos están restringidos a ID de nodo y ID de destino de bordes OUT (para disminuir el tamaño de los datos), para su Id. De nodo e ID de destino de los bordes también. Los búferes de ordenación y fusión se han aumentado a 1.5 Gb, flujos de fusión 80.
Se puede ver claramente que Job2 es el problema real de todo el algoritmo. Genera una gran cantidad de datos que deben ser ordenados/copiados/fusionados. Esto básicamente mata el rendimiento de mi algoritmo para ciertos conjuntos de datos. ¿Puede alguien guiarme sobre cómo mejorar el algoritmo (estaba pensando en crear un Job2 iterativo ["procesar" solo M nodos de N en cada iteración hasta que cada nodo sea "procesado"], pero he abandonado esta idea por ahora) . En mi opinión, la salida del mapa de Job2 debería reducirse para evitar costosos procesos de clasificación/fusión, que matan el rendimiento.
También he implementado el mismo algoritmo (3 trabajos, el mismo patrón de "comunicación", también problema "Job2") para la plataforma Giraph. Sin embargo, Giraph es una plataforma en memoria y el algoritmo para los mismos conjuntos de datos "problemáticos" da como resultado una OutOfMemoryException.
Para cualquier comentario, comentario, guía, le agradeceré.
ACTUALIZACIÓN
voy a cambiar el algoritmo "drásticamente". Encontré este artículo Counting Triangles.
Una vez que se implemente el código, voy a publicar mi opinión aquí y un código más detallado (si este enfoque será exitoso).
UPDATE_2
Al final he terminado "modificar" NodeIterator algoritmo ++ para mis necesidades (papel Yahoo está disponible a través de un enlace en el artículo). Desafortunadamente, aunque puedo ver una mejora en el rendimiento, el resultado final no es tan bueno como esperaba. La conclusión a la que llegué es que el clúster que tengo disponible es demasiado pequeño para que los cálculos de LCC sean factibles para estos conjuntos de datos específicos. Entonces la pregunta permanece, o mejor dicho evoluciona. ¿Alguien sabe de un algoritmo eficiente distribuido/secuencial para calcular LCC o triángulos con recursos limitados disponibles? (De ninguna manera estoy diciendo que el algoritmo NodeIterator ++ es malo, simplemente declaro que los recursos que están disponibles para mí simplemente no son suficientes).
simplemente disparando en la oscuridad ... has probado [el trabajo de clustering de mahout] (https://builds.apache.org/job/Mahout-Quality/javadoc/org/apache/mahout/graph/common/LocalClusteringCoefficientJob.html) –
No, investigaré eso. Thx por un consejo. – alien01
¿podría arreglarlo? ¿Qué emite el reduce() para Job2? –