Іскра, оптимально розділивши один RDD на два


10

У мене є великий набір даних, який мені потрібно розділити на групи за певними параметрами. Я хочу, щоб робота пройшла максимально ефективно. Я можу передбачити два способи цього

Варіант 1 - Створіть карту з оригінального RDD та фільтра

def customMapper(record):
    if passesSomeTest(record):
        return (1,record)
    else:
        return (0,record)

mappedRdd = rddIn.map(lambda x: customMapper(x))
rdd0 = mappedRdd.filter(lambda x: x[0]==0).cache()
rdd1 = mappedRdd.filter(lambda x: x[1]==1).cache()

Варіант 2 - Фільтруйте оригінальний RDD безпосередньо

def customFilter(record):
    return passesSomeTest(record)

rdd0 = rddIn.filter(lambda x: customFilter(x)==False).cache()
rdd1 = rddIn.filter(customFilter).cache()

Метод кулака повинен повторювати всі записи оригінального набору даних 3 рази, де другий повинен це зробити лише двічі, за звичайних обставин, однак, іскра робить деякі поза кадром побудови графіків, так що я міг уявити, що вони ефективно зроблено таким же чином. Мої запитання: а.) Чи є один метод більш ефективним, ніж інший, чи побудова іскрового графіка робить їх еквівалентом b.) Чи можливо це розщеплення за один прохід


Я також знайшов себе з дуже подібною проблемою, і не знайшов рішення. Але що насправді відбувається, не зрозуміло з цього коду, оскільки іскра має "ледачу оцінку" і, мабуть, здатна виконати лише те, що реально потрібно виконати, а також поєднувати карти, фільтри та все, що можна зробити разом. Тож можливо те, що ви описуєте, може статися за один прохід. Хоча недостатньо знайомі з ледачими механізмами оцінювання. Насправді я щойно помітив .cache (). Можливо, є спосіб зробити лише один .cache () та отримати повний результат?
користувач3780968

Відповіді:


9

Перш за все, дозвольте сказати, що я не фахівець з іскор; Я використовував його досить багато останніх місяців, і я вважаю, що зараз це розумію, але я можу помилятися.

Отже, відповідаючи на ваші запитання:

а.) вони рівнозначні, але не так, як ви це бачите; Іскра не оптимізує графік, якщо вам цікаво, але customMapperв обох випадках все одно буде виконано двічі; це пов'язано з тим , що для іскри, rdd1і rdd2два абсолютно різних РДУ, і він буде будувати граф перетворення від низу до верху , починаючи від лаврового листа; тому Варіант 1 перекладається на:

rdd0 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==0).cache()
rdd1 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==1).cache()

Як ви вже сказали, customMapperвиконується двічі (до того ж, також rddInбуде прочитаний двічі, а це означає, що якщо він виходить з бази даних, це може бути навіть повільніше).

б.) є спосіб, вам просто потрібно рухатися cache()в потрібному місці:

mappedRdd = rddIn.map(lambda x: customMapper(x)).cache()
rdd0 = mappedRdd.filter(lambda x: x[0]==0)
rdd1 = mappedRdd.filter(lambda x: x[0]==1)

Роблячи це, ми говоримо іскру, що вона може зберігати часткові результати mappedRdd; Потім вони використовуватимуть ці часткові результати як для, так rdd1і для rdd2. З точки зору іскри це еквівалентно:

mappedRdd = rddIn.map(lambda x: customMapper(x)).saveAsObjectFile('..')
# forget about everything
rdd0 = sc.objectFile('..').filter(lambda x: x[0]==0)
rdd1 = sc.objectFile('..').filter(lambda x: x[0]==1)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.