2012-01-06 23 views
13

Tengo más de 10 millones de fotos guardadas en el sistema de archivos local. Ahora quiero revisar cada uno de ellos para analizar el binario de la foto y ver si es un perro. Básicamente, quiero hacer el análisis en un entorno de hadoop agrupado. El problema es ¿cómo debo diseñar la entrada para el método de mapa? digamos, en el método de mapa, new FaceDetection(photoInputStream).isDog() es toda la lógica subyacente para el análisis.Hadoop: cómo acceder (muchas) imágenes de fotos para ser procesadas por mapa/reducir?

Específicamente, ¿Debo cargar todas las fotos a HDFS? Asumir sí,

  1. ¿Cómo puedo utilizar en el método map?

  2. ¿Está bien hacer que la entrada (a la map) como un archivo de texto que contiene la totalidad de la ruta foto (en HDFS) con cada una línea, y en el método de mapa, cargar el binario como: photoInputStream = getImageFromHDFS(photopath); (En realidad , lo que es el método correcto para cargar el archivo de HDFS durante la ejecución del método mapa?)

parece echo de menos algunos conocimientos sobre el principio básico para hadoop, map/reduce y hdfs, pero puede usted por favor señalarme en términos de la pregunta anterior, ¡Gracias!

+0

¿Pudo lograr esto? En realidad estoy tratando de hacer algo similar, pero no tengo mucha idea sobre cómo proceder – user3527975

Respuesta

0

Estaba en un proyecto hace un tiempo (2008?) Donde hicimos algo muy similar con Hadoop. Creo que inicialmente usamos HDFS para almacenar las imágenes, luego creamos un archivo de texto que enumeró los archivos para procesar. El concepto es que está usando map/reduce para dividir el archivo de texto y distribuirlo en la nube, permitiendo que cada nodo procese algunos de los archivos en función de la parte de la lista que reciben. Lo siento, no recuerdo detalles más explícitos, pero este fue el enfoque general.

18

¿cómo puedo usarlos en el método del mapa?

El principal problema es que cada archivo va a estar en un archivo. Entonces, si tienes archivos de 10M, tendrás mapeadores de 10M, lo cual no suena terriblemente razonable. Es posible que desee considerar pre serializar los archivos en SequenceFiles (una imagen por par clave-valor). Esto hará que la carga de los datos en el trabajo de MapReduce sea nativa, para que no tenga que escribir ningún código complicado. Además, podrá almacenar todos de sus datos en un SequenceFile, si así lo desea. Hadoop maneja bastante bien la división de SequenceFiles.

Básicamente, la forma en que esto funciona es que tendrá un proceso Java separado que toma varios archivos de imagen, lee los bytes de rayos en la memoria y luego almacena los datos en un par clave-valor en un SequenceFile. Continúa y sigue escribiendo en HDFS. Esto puede demorar un tiempo, pero solo tendrás que hacerlo una vez.


¿Está bien hacer que la entrada (con el mapa) como un archivo de texto que contiene la totalidad de la ruta foto (en HDFS) con cada una línea, y en el método de mapa, cargar el binario como : photoInputStream = getImageFromHDFS (photopath); (En realidad, ¿cuál es el método correcto para cargar archivos desde HDFS durante la ejecución del método de mapa?)

Esto no está bien si tienes cualquier tipo de agrupación razonable (que debiera Si usted está considerando Hadoop para esto) y que realmente quiere estar usando el poder de Hadoop. Su trabajo de MapReduce se disparará y cargará los archivos, pero los mapeadores estarán ejecutando datos locales a los archivos de texto, ¡no a las imágenes! Entonces, básicamente, vas a mezclar los archivos de imágenes en todas partes, ya que JobTracker no está colocando tareas donde están los archivos. Esto generará una cantidad significativa de sobrecarga de red. Si tiene 1TB de imágenes, puede esperar que muchas de ellas se transmitirán a través de la red si tiene más de unos pocos nodos. Esto puede no ser tan malo dependiendo de su situación y el tamaño del clúster (menos de un puñado de nodos).

Si desea hacer esto, puede usar la API FileSystem para crear archivos (desea el método open).

+0

¡Asombroso! específico para la solución SequenceFile, parece un proceso jade de hadoop-off. Prefiero probar este, pero ¿te importa hacer un ejemplo de código para generarlo cargando una imagen local y obtenerla en los HDS? esta es probablemente una solución más completa para otros también. Más interesante pero no necesario, el proceso para la generación de SequenceFile y su carga en HDFS podría ser otro trabajo de hadoop, ¿no? ¡Una vez más, esta es una respuesta muy dedicada y profesional! tan apreciado! – leslie

+0

Una cuestión distinta abordar aún más esta: [aquí] (http://stackoverflow.com/q/8754154/844068) – leslie

+0

yo estaba pasando por el código de [DistCp] (http://goo.gl/k95cd) y tiene 'Toma al menos dos parámetros de línea de cmd.Una URL de origen y una URL de destino. Básicamente, hace un "ls -lR" en la URL de origen, y escribe la salida de forma rotativa en todos los archivos de entrada del mapa. En DistCp también no se considera la ubicación de los datos. En el mapeador, los datos se leen desde la fuente (que puede estar en un nodo diferente) y luego se escriben en el destino (que está en un clúster diferente). Habrá mucho tráfico entre nodos cuando los datos que se copiarán en los clusters sean enormes. No estoy seguro de cómo abordarlo. –

7

I have 10M+ photos saved on the local file system.

Suponiendo que tarda un segundo para poner cada archivo en el archivo de secuencia. Tomará ~ 115 días para la conversión de archivos individuales en un archivo de secuencia. Con el procesamiento paralelo también en una sola máquina, no veo mucha mejoría porque la lectura/escritura del disco será un cuello de botella con la lectura de los archivos de fotos y la escritura del archivo de secuencia. Consulte este artículo de Cloudera en small files problem. También hay una referencia a un script que convierte un archivo tar en un archivo de secuencia y cuánto tiempo le tomó a la conversión.

Básicamente las fotos tienen que ser procesados ​​de una manera distribuida para convertirlos en secuencia. Volver a Hadoop :)

De acuerdo con la Hadoop - The Definitive Guide

Como regla general, cada archivo, directorio, y el bloque se tarda unos 150 bytes. Entonces, por ejemplo, si tuviera un millón de archivos, cada uno teniendo un bloque, necesitaría al menos 300 MB de memoria.

Por lo tanto, cargar directamente 10M de archivos requerirá alrededor de 3.000 MB de memoria para simplemente almacenar el espacio de nombre en el NameNode. Olvídate de reproducir las fotos en los nodos durante la ejecución del trabajo.

Debe haber una mejor manera de resolver este problema.


Otro enfoque es cargar los archivos tal cual en HDFS y utilizar CombineFileInputFormat que combina los archivos pequeños en una fracción de entrada y considera localidad de datos, mientras que el cálculo de las divisiones de entrada. La ventaja de este enfoque es que los archivos pueden cargarse en HDFS tal cual, sin ninguna conversión y tampoco hay demasiados datos compilados en los nodos.

+0

muy buen punto! – leslie

+0

Debe tomar mucho menos de un segundo procesar un archivo de imagen que es de unos pocos MB. Aún así, buen punto. Definitivamente podría escribir un trabajo de M/R que hizo esto. Puedes hacer 1 millón a la vez para que no explotes el nodo de nombre. –

+0

Además, 3000MB no es mucho (obviamente, depende de su hardware). ¡16GB por nodo es muy común y si está ejecutando su namenode por sí mismo, eso es un montón de archivos! Un clúster con el que trabajé tenía 96 GB ... eso estuvo bien :) –

Cuestiones relacionadas