java - tutorial - Speicherlimits mit Hadoop angeben



mapreduce-algorithmus (1)

Überprüfen Sie Ihre ulimit. Von Cloudera in Version 0.20.2, aber ein ähnliches Problem gilt wahrscheinlich für spätere Versionen:

... Wenn Sie mapred.child.ulimit festlegen, ist es wichtig, dass sie mehr als doppelt so groß ist wie der in mapred.child.java.opts festgelegte Wert für die Größe des Heapspeichers. Wenn Sie beispielsweise einen 1G-Heap festlegen, legen Sie mapred.child.ulimit auf 2,5 GB fest. Untergeordnete Prozesse werden jetzt garantiert mindestens einmal forkiert, und die Verzweigung erfordert momentan den doppelten Overhead im virtuellen Speicher.

Es ist auch möglich, dass das Festlegen von mapred.child.java.opts programmatisch "zu spät" ist; Vielleicht möchten Sie überprüfen, ob es wirklich in Kraft tritt, und es in Ihre mapred-site.xml einfügen, falls dies nicht der Fall ist.

Ich versuche, auf einem Hadoop-Cluster einen Job mit hohem Arbeitsspeicher auszuführen (0.20.203). Ich habe die mapred-site.xml geändert, um einige Speicherbeschränkungen zu erzwingen.

  <property>
    <name>mapred.cluster.max.map.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapred.cluster.max.reduce.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapred.cluster.map.memory.mb</name>
    <value>2048</value>
  </property>
  <property>
    <name>mapred.cluster.reduce.memory.mb</name>
    <value>2048</value>
  </property>

In meinem Job gebe ich an, wie viel Speicher ich brauche. Leider muss ich, obwohl ich meinen Prozess mit -Xmx2g (der Job wird mit so viel Speicher wie eine Konsolenanwendung funktionieren), muss ich viel mehr Speicher für meinen Mapper anfordern (als Teilfrage, warum ist das so?) Oder es wurde getötet.

val conf = new Configuration()
conf.set("mapred.child.java.opts", "-Xms256m -Xmx2g -XX:+UseSerialGC");
conf.set("mapred.job.map.memory.mb", "4096");
conf.set("mapred.job.reduce.memory.mb", "1024");

Der Reduktor benötigt kaum Speicherplatz, da ich einen Identity Reducer verwende.

  class IdentityReducer[K, V] extends Reducer[K, V, K, V] {
    override def reduce(key: K,
        values: java.lang.Iterable[V],
        context:Reducer[K,V,K,V]#Context) {
      for (v <- values) {
        context write (key, v)
      }
    }
  }

Der Reduktor verbraucht jedoch immer noch viel Speicher. Ist es möglich, dem Reduzierer andere JVM-Argumente zu geben als dem Mapper? Hadoop tötet den Reducer und behauptet, dass er 3960 MB Speicher nutzt! Und die Reducer scheitern am Ende. Wie ist das möglich?

TaskTree [pid=10282,tipID=attempt_201111041418_0005_r_000000_0] is running beyond memory-limits.
Current usage : 4152717312bytes.
Limit : 1073741824bytes.
Killing task.

UPDATE: selbst wenn ich einen Streaming-Job mit cat als Mapper und uniq als Reducer und -Xms512M -Xmx1g -XX:+UseSerialGC meine Aufgaben 2g virtuellen Speichers! Dies scheint extravagant bei 4x der maximalen Größe des Heapspeichers.

TaskTree [pid=3101,tipID=attempt_201111041418_0112_m_000000_0] is running beyond memory-limits.
Current usage : 2186784768bytes.
Limit : 2147483648bytes.
Killing task.

Update: Die originale JIRA zum Ändern des Konfigurationsformats für die Speichernutzung erwähnt speziell, dass Java-Benutzer hauptsächlich an physischem Speicher interessiert sind, um Thrash zu verhindern. Ich denke, das ist genau das, was ich möchte: Ich möchte nicht, dass ein Knoten einen Mapper hochfährt, wenn nicht genügend physischer Speicher verfügbar ist. Diese Optionen scheinen jedoch alle als Beschränkungen des virtuellen Speichers implementiert worden zu sein, die schwierig zu verwalten sind.





hadoop