नक्शा / कमी क्या है?


84

मैं मानचित्र के बारे में बहुत कुछ सुनता / कम करता हूं, विशेष रूप से Google की व्यापक समानांतर गणना प्रणाली के संदर्भ में। वास्तव में क्या है?


3
@Rinat: फिर भी, यह अभी भी एक अच्छा सवाल है।
बिल कार्विन

3
यकीन है कि मैं कर सकता था और यह Google किया; लेकिन (ए) एसओ को सभी महत्वपूर्ण सवालों के जवाब देने के लिए बढ़ने का इरादा है (हमें उन सवालों को पोस्ट करने के लिए भी प्रोत्साहित किया जाता है जिनके पास हमारे पास पहले से ही उत्तर हैं) और (बी) मैं इस समुदाय को इस पर लेना चाहता था।
लॉरेंस डॉल

जवाबों:


69

Google के MapReduce शोध प्रकाशन पृष्ठ के सार से :

MapReduce एक प्रोग्रामिंग मॉडल है और बड़े डेटा सेट को संसाधित करने और उत्पन्न करने के लिए एक संबद्ध कार्यान्वयन है। उपयोगकर्ता एक मानचित्र फ़ंक्शन निर्दिष्ट करते हैं जो मध्यवर्ती कुंजी / मूल्य जोड़े के एक सेट को उत्पन्न करने के लिए एक कुंजी / मूल्य जोड़ी को संसाधित करता है, और एक कम फ़ंक्शन जो एक ही मध्यवर्ती कुंजी से जुड़े सभी मध्यवर्ती मूल्यों को मिलाता है।

MapReduce का लाभ यह है कि प्रोसेसिंग को कई प्रोसेसिंग नोड्स (कई सर्वर) पर समानांतर में किया जा सकता है, इसलिए यह एक प्रणाली है जो बहुत अच्छी तरह से स्केल कर सकती है।

चूंकि यह कार्यात्मक प्रोग्रामिंग मॉडल से आधारित है , mapऔर reduceप्रत्येक चरण का कोई साइड-इफेक्ट नहीं होता है (एक mapप्रक्रिया के प्रत्येक उपधारा से स्थिति और परिणाम दूसरे पर निर्भर नहीं होते हैं), इसलिए डेटा सेट को मैप किया जा रहा है और कम किया जा सकता है। कई प्रसंस्करण नोड्स पर।

योएल आपकी प्रोग्रामिंग भाषा यह कर सकती है? टुकड़ा चर्चा करता है कि Google में MapReduce के साथ कार्यात्मक प्रोग्रामिंग को समझना कितना आवश्यक था, जो इसके खोज इंजन को शक्ति प्रदान करता है। यदि आप कार्यात्मक प्रोग्रामिंग से अपरिचित हैं और यह स्केलेबल कोड की अनुमति देता है तो यह बहुत अच्छा है।

इन्हें भी देखें: विकिपीडिया: MapReduce

संबंधित प्रश्न: कृपया मानचित्रण की व्याख्या करें


3
बहुत बढ़िया समझाया। और सॉफ्टवेयर बंदर के लिए, एम / आर अविश्वसनीय रूप से कुछ भी लागू करने के लिए अविश्वसनीय रूप से आसान है एक बार जब आप इसे समझते हैं और यहां दिए गए उदाहरणों तक सीमित नहीं हैं। इसके चारों ओर अपना सिर पाने के कई तरीके हैं, कोई इसे कलेक्टर और फ़नल के रूप में सोच रहा होगा।
Esko


16

मानचित्र एक ऐसा कार्य है जो एक सूची के सभी मदों पर एक और फ़ंक्शन लागू करता है, उस पर सभी रिटर्न मानों के साथ एक और सूची बनाने के लिए। ("F से x पर लागू करें" कहने का एक और तरीका है "कॉल f, इसे पास करना x"। इसलिए कभी-कभी यह "कॉल" के बजाय "लागू" कहने के लिए अच्छा लगता है।)

यह है कि मानचित्र को संभवतः C # में लिखा गया है (इसे कहा जाता है Selectऔर मानक पुस्तकालय में है):

public static IEnumerable<R> Select<T, R>(this IEnumerable<T> list, Func<T, R> func)
{
    foreach (T item in list)
        yield return func(item);
}

जैसा कि आप एक जावा दोस्त हैं, और जोएल स्पोलस्की को पूरी तरह से यह बताने के लिए पसंद है कि जावा कितना भद्दा है (वास्तव में, वह झूठ नहीं बोल रहा है, यह भद्दा है, लेकिन मैं आपको जीतने की कोशिश कर रहा हूं), यहाँ मेरा बहुत ही कठिन प्रयास है एक जावा संस्करण (मेरे पास कोई जावा संकलक नहीं है, और मुझे अस्पष्ट रूप से जावा संस्करण 1.1 याद है!)।

// represents a function that takes one arg and returns a result
public interface IFunctor
{
    object invoke(object arg);
}

public static object[] map(object[] list, IFunctor func)
{
    object[] returnValues = new object[list.length];

    for (int n = 0; n < list.length; n++)
        returnValues[n] = func.invoke(list[n]);

    return returnValues;
}

मुझे यकीन है कि इसे दस लाख तरीकों से सुधारा जा सकता है। लेकिन यह मूल विचार है।

कम करना एक ऐसा कार्य है जो सूची के सभी आइटमों को एकल मान में बदल देता है। ऐसा करने के लिए, इसे एक और फ़ंक्शन देने की आवश्यकता है funcजो दो वस्तुओं को एक मूल्य में बदल देता है। यह पहले दो आइटम देकर काम करेगाfunc । फिर तीसरे आइटम के साथ उस का परिणाम। फिर चौथे आइटम के साथ उस का परिणाम, और इसी तरह जब तक सभी आइटम चले गए और हम एक मूल्य के साथ छोड़ दिए गए हैं।

C # कम में कहा जाता है Aggregateऔर फिर से मानक पुस्तकालय में है। मैं सीधे Java वर्जन पर जाऊंगा:

// represents a function that takes two args and returns a result
public interface IBinaryFunctor
{
    object invoke(object arg1, object arg2);
}

public static object reduce(object[] list, IBinaryFunctor func)
{
    if (list.length == 0)
        return null; // or throw something?

    if (list.length == 1)
        return list[0]; // just return the only item

    object returnValue = func.invoke(list[0], list[1]);

    for (int n = 1; n < list.length; n++)
        returnValue = func.invoke(returnValue, list[n]);

    return returnValue;
}

इन जावा संस्करणों को उनके साथ जोड़ने के लिए जेनरिक की आवश्यकता है, लेकिन मुझे नहीं पता कि जावा में यह कैसे करना है। लेकिन आपको फ़ंक्शनलर्स प्रदान करने के लिए उन्हें अनाम आंतरिक कक्षाएं पास करने में सक्षम होना चाहिए:

string[] names = getLotsOfNames();

string commaSeparatedNames = (string)reduce(names, 
   new IBinaryFunctor {
       public object invoke(object arg1, object arg2)
           { return ((string)arg1) + ", " + ((string)arg2); }
   }

उम्मीद है कि जनजातियों को जातियों से छुटकारा मिलेगा। C # में समतुल्य प्रकार:

string commaSeparatedNames = names.Aggregate((a, b) => a + ", " + b);

यह "शांत" क्यों है? छोटे टुकड़ों में बड़ी गणनाओं को तोड़ने के सरल तरीके, इसलिए उन्हें अलग-अलग तरीकों से एक साथ वापस रखा जा सकता है, हमेशा शांत होते हैं। जिस तरह से Google इस विचार को लागू करता है, वह समानांतर है, क्योंकि मैप और कम दोनों को कई कंप्यूटरों पर साझा किया जा सकता है।

लेकिन प्रमुख आवश्यकता यह नहीं है कि आपकी भाषा मानों के रूप में कार्य कर सकती है। कोई भी OO भाषा ऐसा कर सकती है। समानांतरकरण की वास्तविक आवश्यकता यह है कि आप जिन छोटे funcकार्यों को पास करने के लिए नक्शा बनाते हैं और कम करते हैं उन्हें किसी भी राज्य का उपयोग या अद्यतन नहीं करना चाहिए। उन्हें एक मान वापस करना चाहिए जो केवल उनके पास दिए गए तर्क (नों) पर निर्भर है। अन्यथा, परिणाम पूरी तरह से खराब हो जाएंगे जब आप पूरी चीज़ को समानांतर में चलाने की कोशिश करेंगे।


2
कुल मिलाकर एक अच्छा जवाब, लायक 1; हालांकि जावा पर जैब पसंद नहीं था - लेकिन मैंने सी से जावा में जाने के बाद से फ़ंक्शन मानों को याद किया है, और सहमत हूं कि जावा में उनकी उपलब्धता लंबे समय से अधिक है।
लॉरेंस डोल

1
जावा पर एक गंभीर बात नहीं थी - इसमें तीन या इतनी खामियां हैं जो मुझे C # अभी पसंद करने के लिए पर्याप्त हैं, लेकिन C # में उन खामियों की एक सूची भी है जो शायद किसी दिन मुझे दूसरी भाषा के बारे में बताएगी।
डैनियल इयरविकर

वैसे, मुझे बहुत अच्छा लगेगा अगर कोई उदाहरणों को संपादित कर सके ताकि वे जावा जेनेरिक का उपयोग करें, यदि यह वास्तव में संभव है। या यदि आप संपादित नहीं कर सकते हैं तो स्निपेट यहाँ पोस्ट करें और मैं संपादित करूँगा।
डैनियल ईयरविकर

मैंने संपादित करना शुरू किया, लेकिन मानचित्र () विधि रिटर्न प्रकार की एक सरणी बनाता है; जावा सामान्य प्रकार के सरणियों को बनाने की अनुमति नहीं देता है। मैं इसे एक सूची का उपयोग करने के लिए बदल सकता था (और संभवतः इसे एक सरणी में बदल सकता हूं), लेकिन मैं उस समय महत्वाकांक्षा से बाहर भाग गया।
माइकल मायर्स

1
क्लोजर सिंटैक्स के समान (ए, बी) => ए + "," + बी कुछ ऐसा था जिसे मैं वास्तव में जावा 7 में देख रहा था, विशेष रूप से कुछ नए एपीआई सामान के साथ जो ऐसा दिखता है कि यह सिंटैक्स में जाएगा। इस तरह से बहुत क्लीनर बनाया है; बहुत बुरा यह नहीं लगता कि ऐसा होगा।
एडम जस्कविक्ज़

2

बहुत लंबे वेफले या बहुत कम अस्पष्ट ब्लॉग पोस्टों से सबसे अधिक निराश होने के बाद मैंने अंततः इस बहुत अच्छे कठोर संक्षिप्त पेपर की खोज की

फिर मैं आगे बढ़ा और स्कैला में अनुवाद करके इसे और अधिक संक्षिप्त बना दिया, जहां मैंने सबसे सरल मामला प्रदान किया है जहां एक उपयोगकर्ता बस mapऔर केवल इस पर विचार करता है औरreduce आवेदन के कुछ हिस्सों भागों को करता है। Hadoop / Spark में, कड़ाई से बोलते हुए, प्रोग्रामिंग का एक अधिक जटिल मॉडल कार्यरत है जिसके लिए उपयोगकर्ता को स्पष्ट रूप से यहां उल्लिखित 4 और कार्यों को निर्दिष्ट करने की आवश्यकता होती है: http://en.wikipedia.org/wiki/MapReduce#Dataflow

import scalaz.syntax.id._

trait MapReduceModel {
  type MultiSet[T] = Iterable[T]

  // `map` must be a pure function
  def mapPhase[K1, K2, V1, V2](map: ((K1, V1)) => MultiSet[(K2, V2)])
                              (data: MultiSet[(K1, V1)]): MultiSet[(K2, V2)] = 
    data.flatMap(map)

  def shufflePhase[K2, V2](mappedData: MultiSet[(K2, V2)]): Map[K2, MultiSet[V2]] =
    mappedData.groupBy(_._1).mapValues(_.map(_._2))

  // `reduce` must be a monoid
  def reducePhase[K2, V2, V3](reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)])
                             (shuffledData: Map[K2, MultiSet[V2]]): MultiSet[V3] =
    shuffledData.flatMap(reduce).map(_._2)

  def mapReduce[K1, K2, V1, V2, V3](data: MultiSet[(K1, V1)])
                                   (map: ((K1, V1)) => MultiSet[(K2, V2)])
                                   (reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)]): MultiSet[V3] =
    mapPhase(map)(data) |> shufflePhase |> reducePhase(reduce)
}

// Kinda how MapReduce works in Hadoop and Spark except `.par` would ensure 1 element gets a process/thread on a cluster
// Furthermore, the splitting here won't enforce any kind of balance and is quite unnecessary anyway as one would expect
// it to already be splitted on HDFS - i.e. the filename would constitute K1
// The shuffle phase will also be parallelized, and use the same partition as the map phase.  
abstract class ParMapReduce(mapParNum: Int, reduceParNum: Int) extends MapReduceModel {
  def split[T](splitNum: Int)(data: MultiSet[T]): Set[MultiSet[T]]

  override def mapPhase[K1, K2, V1, V2](map: ((K1, V1)) => MultiSet[(K2, V2)])
                                       (data: MultiSet[(K1, V1)]): MultiSet[(K2, V2)] = {
    val groupedByKey = data.groupBy(_._1).map(_._2)
    groupedByKey.flatMap(split(mapParNum / groupedByKey.size + 1))
    .par.flatMap(_.map(map)).flatten.toList
  }

  override def reducePhase[K2, V2, V3](reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)])
                             (shuffledData: Map[K2, MultiSet[V2]]): MultiSet[V3] =
    shuffledData.map(g => split(reduceParNum / shuffledData.size + 1)(g._2).map((g._1, _)))
    .par.flatMap(_.map(reduce))
    .flatten.map(_._2).toList
}


0

मानचित्र एक मूल JS विधि है जिसे किसी सरणी में लागू किया जा सकता है। यह मूल सरणी में प्रत्येक तत्व के लिए मैप किए गए कुछ फ़ंक्शन के परिणामस्वरूप एक नया सरणी बनाता है। इसलिए यदि आप किसी फ़ंक्शन (तत्व) {रिटर्न एलिमेंट * 2;} को मैप करते हैं, तो यह हर एलीमेंट को दोगुना करने के साथ एक नया एरे लौटाएगा। मूल सरणी असम्बद्ध हो जाएगी।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

कम करना एक मूल JS विधि है जिसे किसी सरणी में भी लागू किया जा सकता है। यह एक अरै में फंक्शन को लागू करता है और इसमें एक आरंभिक आउटपुट मान होता है जिसे एक संचायक कहा जाता है। यह सरणी में प्रत्येक तत्व के माध्यम से लूप करता है, एक फ़ंक्शन लागू करता है, और उन्हें एक एकल मान (जो संचायक के रूप में शुरू होता है) तक कम कर देता है। यह उपयोगी है क्योंकि आपके पास कोई भी आउटपुट हो सकता है, आपको बस उस प्रकार के संचायक से शुरू करना होगा। इसलिए अगर मैं किसी वस्तु में कुछ घटाना चाहता हूं, तो मैं एक संचयकर्ता {} से शुरू करूंगा।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?v=a


0

मानचित्र छोटा करना:

कुछ बड़ा चलाने के लिए, हम अपने कार्यालय में विभिन्न कंप्यूटर की गणना शक्ति का उपयोग कर सकते हैं। विभिन्न कंप्यूटरों के बीच कार्य को विभाजित करना मुश्किल है। यह MapReduce लाइब्रेरी द्वारा किया जाता है।

मूल विचार यह है कि आप नौकरी को दो भागों में विभाजित करते हैं: एक नक्शा, और एक कमी। मैप मूल रूप से समस्या लेता है, इसे उप-भागों में विभाजित करता है, और उप-भागों को विभिन्न मशीनों में भेजता है - इसलिए सभी टुकड़े एक ही समय में चलते हैं। उप-भागों से परिणामों को कम कर देता है और एक ही उत्तर पाने के लिए उन्हें वापस एक साथ जोड़ देता है।

इनपुट अभिलेखों की एक सूची है। मानचित्र संगणना का परिणाम कुंजी / मान युग्मों की एक सूची है। मूल्यों के प्रत्येक सेट को कम करें जिसमें समान कुंजी है, और उन्हें एक ही मूल्य में जोड़ता है। आप यह नहीं बता सकते हैं कि क्या नौकरी 100 टुकड़ों या 2 टुकड़ों में विभाजित हो गई थी; अंतिम परिणाम एक ही नक्शे के परिणाम की तरह दिखता है।

कृपया सरल मानचित्र देखें और कार्यक्रम को कम करें:

मैप फ़ंक्शन का उपयोग हमारी मूल सूची में कुछ फ़ंक्शन को लागू करने के लिए किया जाता है और इसलिए एक नई सूची बनाई जाती है। पायथन में मानचित्र () फ़ंक्शन एक फ़ंक्शन और एक सूची तर्क के रूप में लेता है। सूची के प्रत्येक आइटम पर फ़ंक्शन लागू करके एक नई सूची दी गई है।

li = [5, 7, 4, 9] 
final_list = list(map(lambda x: x*x , li)) 
print(final_list)  #[25, 49, 16, 81]

पायथन में कम () फ़ंक्शन एक फ़ंक्शन और एक सूची में तर्क के रूप में होता है। फ़ंक्शन को लैंबडा फ़ंक्शन और एक सूची के साथ बुलाया जाता है और एक नया घटा हुआ परिणाम वापस किया जाता है। यह सूची के जोड़े पर दोहरावदार संचालन करता है।

#reduce func to find product/sum of list
x=(1,2,3,4)
from functools import reduce
reduce(lambda a,b:a*b ,x) #24
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.