سؤال

يبدو مُخفض عدد الكلمات البسيط في روبي كما يلي:

#!/usr/bin/env ruby
wordcount = Hash.new
STDIN.each_line do |line|
keyval = line.split("|")
wordcount[keyval[0]] = wordcount[keyval[0]].to_i+keyval[1].to_i
end

wordcount.each_pair do |word,count|
puts "#{word}|#{count}"
end

فإنه يحصل في STDIN جميع القيم المتوسطة لمصممي الخرائط.وليس من مفتاح معين.لذا، في الواقع لا يوجد سوى مخفض واحد للجميع (وليس مخفضًا لكل كلمة أو لكل مجموعة من الكلمات).

ومع ذلك، في أمثلة Java، رأيت هذه الواجهة التي تحصل على مفتاح وقائمة من القيم كما هو الحال في الداخل.مما يعني أنه يتم تجميع قيم الخريطة المتوسطة حسب المفتاح قبل التخفيض ويمكن تشغيل المخفضات بالتوازي:

public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {
            public void reduce(Text key, Iterator<IntWritable> values, OutputCollector<Text, IntWritable> output, Reporter reporter) throws IOException {
              int sum = 0;
              while (values.hasNext()) {
                sum += values.next().get();
              }
              output.collect(key, new IntWritable(sum));
            }
          }

هل هذه ميزة جافا فقط؟أو هل يمكنني القيام بذلك باستخدام Hadoop Streaming باستخدام Ruby؟

هل كانت مفيدة؟

المحلول

سيتم تشغيل المخفضات دائمًا بالتوازي، سواء كنت تستخدم البث أم لا (إذا كنت لا ترى ذلك، فتحقق من تعيين تكوين الوظيفة للسماح بمهام تقليل متعددة - راجع Mapred.reduce.tasks في مجموعتك أو تكوين الوظيفة ).الفرق هو أن إطار العمل يحزم الأشياء بشكل أفضل قليلاً بالنسبة لك عند استخدام Java مقابل البث.

بالنسبة لـ Java، تحصل مهمة التصغير على مكرر لجميع القيم الخاصة بمفتاح معين.وهذا يجعل من السهل تتبع القيم إذا كنت، على سبيل المثال، تقوم بجمع مخرجات الخريطة في مهمة التصغير الخاصة بك.في البث، تحصل حرفيًا على دفق من أزواج القيمة الرئيسية.أنت نكون نضمن أن القيم سيتم ترتيبها حسب المفتاح، وأنه لن يتم تقسيم ذلك المفتاح المحدد عبر مهام تقليل، ولكن أي تتبع حالة تحتاجه هو أمر متروك لك.على سبيل المثال، في Java، يأتي مخرج الخريطة إلى المخفض الخاص بك بشكل رمزي في النموذج

key1 ، {val1 ، val2 ، val3} key2 ، {val7 ، val8}

مع البث، يبدو الإخراج الخاص بك بدلاً من ذلك

key1 ، val1 key1 ، val2 key1 ، val3 key2 ، val7 key2 ، val8

على سبيل المثال، لكتابة مخفض يحسب مجموع القيم لكل مفتاح، ستحتاج إلى متغير لتخزين آخر مفتاح رأيته ومتغير لتخزين المجموع.في كل مرة تقرأ فيها زوجًا جديدًا من المفاتيح والقيمة، عليك القيام بما يلي:

  1. تحقق مما إذا كان المفتاح مختلفًا عن المفتاح الأخير.
  2. إذا كان الأمر كذلك، فأخرج المفتاح والمجموع الحالي، وأعد تعيين المجموع إلى الصفر.
  3. أضف القيمة الحالية إلى مجموعك وقم بتعيين المفتاح الأخير للمفتاح الحالي.

هث.

نصائح أخرى

ولم أحاول Hadoop الجري نفسي ولكن من قراءة مستندات اعتقد انه يمكن تحقيق السلوك الموازي مماثل.

وبدلا من تمرير مفتاح مع القيم المرتبطة بكل المخفض، تدفق مجموعة إرادة إخراج معين من المفاتيح. فإنه يضمن أيضا أن القيم مع نفس المفاتيح لن يتم تقسيم أكثر من مخفضات متعددة. وهذا يختلف إلى حد ما من وظائف Hadoop العادية، ولكن حتى مع ذلك، سيتم توزيع تقليل العمل على مخفضات متعددة.

وحاول استخدام الخيار -verbose للحصول على مزيد من المعلومات حول ما يحدث في الواقع. يمكنك أيضا محاولة لتجربة مع خيار -D mapred.reduce.tasks=X حيث X هو الرقم المطلوب مخفضات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top