сравнение 2 наборов данных возможно с параллельным / асинхронным / параллельным подходом - PullRequest
0 голосов
/ 29 августа 2018

В настоящее время я пытаюсь улучшить существующий механизм ( для сравнения данных из 2 источников, реализованный в perl5 ) и хотел бы вместо него использовать perl6.

Мой целевой объем данных составляет около 20-30 ГБ в несжатых плоских файлах. С точки зрения строк, файл может содержать от 18 до 28 миллионов строк. В каждой строке около 40-50 столбцов.

Я выполняю такой тип выверки данных ежедневно, и для чтения из файла и заполнения хеша может потребоваться ~ 10 минут. ~ 20 минут потрачено на чтение обоих файлов и заполнение хеша.

Процесс сравнения занимает около 30-50 минут, включая итерации по хешу, сбор желаемых результатов и запись в выходной файл (csv, psv).

В целом процесс может занять от 30 минут до 60 минут на 32-ядерном двухъядерном процессоре xeon с 256 ГБ ОЗУ, включая прерывистую загрузку сервера.

Теперь я пытаюсь сократить общее время обработки еще больше.

Вот мой текущий однопоточный подход с использованием perl5.

  1. выборка данных из 2 источников (, скажем, s1 и s2 ) один за другим и заполнение моего хэша на основе пар ключ-значение. Источником данных может быть либо плоский CSV-файл, либо PSV-файл, либо запрос массива массива запроса базы данных через клиент DBI. Для начала данные всегда сортируются.
  2. Если быть точным, я читаю файл построчно, разделяю поля и выбираю нужные индексы для ключа, пары значений и вставляю в хеш.
  3. После сбора данных и заполнения хэша желаемыми парами ключ / значение, я начинаю сравнивать и собирать результаты ( основное сравнение с тем, что отсутствует или отличается в s2 по сравнению с s1 и наоборот ).
  4. вывод дампа в файл Excel ( очень дорого, если число строк велико, как ~ 1 миллион или больше ) или в простом CSV ( дешевая операция. Предпочтительный метод ) .

Мне было интересно, смогу ли я как-нибудь сделать первый шаг параллельно, то есть собрать данные из обоих источников одновременно и заполнить мой глобальный хэш, а затем перейти к сравнению и выводу вывода?

Какие опции может предоставить perl6 для решения этой ситуации? Я читал о параллелизме, асинхронных и параллельных операциях с использованием perl6, но я не уверен, какой из них мне поможет.

Я был бы очень признателен за любые общие указания по этому вопросу. Надеюсь, я хорошо объяснил свою проблему, но, к сожалению, мне нечего показать по , что я пробовал до сих пор? , и причина в том, что я только начинаю решать эту проблему. Я просто не могу понять, что такое однопоточный подход, и мне нужна помощь.

Спасибо.

EDIT

Поскольку мое существующее изложение проблемы было признано сообществом как «слишком широкое» - позвольте мне попытаться выделить мои болевые точки ниже:

  1. Я бы хотел сравнить файлы, используя все 32 ядра, если это возможно. Я просто не могу придумать стратегию или первоначальную идею.
  2. Какие новые методы доступны или применимы с perl6 для решения этой проблемы или типа проблемы.
  3. Если я порождаю 2 процесса для чтения файла (ов) и сбора данных - возможно ли вернуть результат в виде массива или хеша?
  4. Можно ли сравнить данные (, хранящиеся в хэше ) параллельно?

Моя текущая логика сравнения p5 показана ниже для справки. Надеюсь, что это поможет, и не позволяйте этому вопросу закрыться.

package COMP;

use strict;
use Data::Dumper;


sub comp 
{
  my ($data,$src,$tgt) = @_; 
  my $result = {};

  my $ms    = ($result->{ms} = {});
  my $mt    = ($result->{mt} = {});
  my $diff  = ($result->{diff} = {});

  foreach my $key (keys %{$data->{$src}})
  {
    my $src_val = $data->{$src}{$key};
    my $tgt_val = $data->{$tgt}{$key};

    next if ($src_val eq $tgt_val);

    if (!exists $data->{$tgt}{$key}) {
      push (@{$mt->{$key}}, "$src_val|NULL");
    }
    if (exists $data->{$tgt}{$key} && $src_val ne $tgt_val) {
      push (@{$diff->{$key}}, "$src_val|$tgt_val") 
    }
  }

  foreach my $key (keys %{$data->{$tgt}})
  {
    my $src_val = $data->{$src}{$key};
    my $tgt_val = $data->{$tgt}{$key};

    next if ($src_val eq $tgt_val);

    if (!exists $data->{$src}{$key}) {
      push (@{$ms->{$key}},"NULL|$tgt_val");
    }
  } 

  return $result;
}

1;

Если кто-то захочет попробовать, вот пример выходных данных и используемый тестовый скрипт.

вывод сценария

[User@Host:]$ perl testCOMP.pl 
$VAR1 = {
          'mt' => {
                    'Source' => [
                                  'source|NULL'
                                ]
                  },
          'ms' => {
                    'Target' => [
                                  'NULL|target'
                                ]
                  },
          'diff' => {
                      'Sunday_isit' => [
                                         'Yes|No'
                                       ]
                    }
        };

Тестовый скрипт

[User@Host:]$  cat testCOMP.pl 
#!/usr/bin/env perl

use lib $ENV{PWD};
use COMP;
use strict;
use warnings;
use Data::Dumper;

my $data2 = {
  f1 => {
    Amitabh => 'Bacchan',
    YellowSun => 'Yes', 
    Sunday_isit => 'Yes',
    Source => 'source',
  },
  f2 => {
    Amitabh => 'Bacchan',
    YellowSun => 'Yes', 
    Sunday_isit => 'No',
    Target => 'target',
  },
};

my $result = COMP::comp ($data2,'f1','f2');
print Dumper $result;
[User@Host:]$ 
...