Perl5 как язык для изучения данных

[ЗАВЕРШЕНО] Последнее обновление по в пт, 17 апр. 2026    источник
 

Изучение данных

Введение в серию – Пост 0 из N
Эта статья является первой в серии, документирующей совместную разработку движка векторных баз данных (VDBE), написанной полностью на Perl5 + PDL. Позже посты проходят через каждый компонент этого двигателя; этот устанавливает ступень. Основной импульс для этой серии заключается не в том, чтобы вы сбросили свой VDBE, поскольку я не предъявляю претензий к производительности, а в том, чтобы показать, как можно использовать Perl для достижения практически всего, чего вы можете достичь с помощью любого другого языка, но умнее!


Содержание


1. Почему Perl5 для Data Science?

Когда специалисты по изучению данных обсуждают выбор языка, разговор быстро сходится на Python, R или Julia. Perl5 редко занимает место за столом, но он имеет убедительный набор признаков, которые заслуживают второго взгляда. Эти черты за эти годы не существенно изменились (Perl5 всегда был таким!), но если только не Вы были подвержены языку и научились ценить его красоту, рациональность, гибкость, выразительность и на самом деле использовали его для продвижения своей работы впередВы бы не знали, что эти функции не только бесплатны с Perl5, но и могут помочь вам продвигать ваши проекты вперед.

Развертывание с нулевой установкой

Perl5 поставляется в качестве компонента по умолчанию практически для каждой UNIX-подобной операционной системы – дистрибутивы Linux, macOS, BSD и многие встроенные среды Linux – все это включает в себя работу перл бинарные из коробки. Python продвигается здесь, но все еще часто можно найти автономные серверы, сетевые устройства или узлы входа в HPC
где присутствует Перл, а полного стека питона нет. Конвейер данных, записанный в Perl, может работать в первый день без конда окружающая среда, венили контейнер.

Переносимость от центра обработки данных к границе

Тот же сценарий, который анализирует терабайтный набор данных на 256-ядерном узле HPC, может с незначительными изменениями конфигурации работать на Raspberry Pi, шлюзе IoT или встроенном контроллере. Перл’однобинарная модель развертывания и низкие эксплуатационные расходы делают ее подлинной “однократная запись, запуск в любом месте” язык в среде, где Python’s переводчик над головой или Юлия’Время разминки JIT было бы неприемлемым.

Если вы планируете развертывать в любом месте, и everywhere Perl5 – ваш очевидный выбор.

Наследие, основанное на обработке текста и данных

Перл был разработан с нуля для обработки текста, регулярных выражений и “клей” Работа между компонентами системы. На практике в конвейерах научных данных преобладают не численные вычисления, а смена данных: чтение разнородных форматов файлов, очистка беспорядочных записей, объединение наборов данных из разных источников и маршрутизация результатов до последующих потребляющих компонентов.

Перл’движок регулярных выражений остается одним из самых мощных доступных, и однолинейные системы могут выполнять задачи очистки данных, которые потребуют вспомогательных библиотек на других языках.

Если вы находитесь в области научных вычислений, вы, возможно, столкнулись с понятием системы управления рабочим процессом и воспроизводимые исследования. Они оба полагаются на выполнение сквозных преобразований данных и рабочих процессов, чтобы устранить ручную, подверженную ошибкам и утомительную деятельность, которую аналитики и ученые должны выполнять, чтобы превратить свои данные в аналитику и выводы соответственно.

В этом смелом новом мире, Perl5’богатая история позволяет ему сиять как в качестве компонента рабочих процессов, так и в качестве языка приложения, который реализует эти рабочие процессы.

CPAN: испытанная битвой экосистема модулей

Комплексная сеть архивов Perl (CPAN) содержит более 200 000 модулей по всем возможным доменам. Хотя предложения по Data Science не так обширны, как Python, основные компоненты для выделенных разработчиков существуют там.:

PDL (Perl Data Language) – векторизованные числовые вычисления с сильно типизированными N-мерными массивами (покрытыми ниже).

PDL::Stats – описательная статистика, регрессия, кластеризация (k-средства, мини-пакетные k-средства) и многое другое, построенное на основе PDL ndarrays.

DBI + десятки драйверов баз данных – доступ SQL к каждой крупной СУРБД.

MCE (Many-Core Engine) – структурированный параллелизм для рабочих нагрузок с общей и распределенной памятью.

Inline::C, Inline::CPP – встраивание кода C или C++ непосредственно в исходный файл Perl; компилятор вызывается прозрачно при первом запуске сценария, что делает тривиальным удаление критически важных ядер производительности в программу чисто Perl без полной системы сборки XS.

Современный Перл не твой дед’s Перл

Приведенные ниже функции взяты непосредственно из официальных примечаний к выпуску (perl5360delta, perl5380delta, perl5400delta) и организованы путем выпуска, в котором они достигли стабильного статуса или были впервые введены. Выделены только функции, относящиеся к научным и научно-вычислительным рабочим нагрузкам.

Перл 5.36 – май 2022

Именованные подпрограммные подписи (стабильные с 5.36; экспериментальные с 5.20) – параметры функции теперь объявляются по имени, с необязательными значениями по умолчанию. The //= и ||= операторы значения по умолчанию добавлены к подписям в версии 5.38, что позволяет использовать значения по умолчанию, которые запускаются неопределённая Ложность соответственно:

  use v5.36;
  sub clamp ($val, $lo = 0, $hi //= 1) {
      $val < $lo ? $lo : $val > $hi ? $hi : $val;
  }
  use v5.40;
  use builtin 'indexed';

for my ($i, $val) (indexed @scores)  { ... } # index and value

Или захватить несколько значений одновременно

  use v5.40;

for my ($val1, $val2, $val3) (@scores)  { ... }

Перл 5.38 – июль 2023

  use feature 'class';
  no warnings 'experimental::class';

class Vector2D {
      field $x :param;
      field $y :param;
      method magnitude { sqrt($x**2 + $y**2) }
  }
  my $v = Vector2D->new(x => 3, y => 4);
  say $v->magnitude;    # 5

Перл 5.40 – июнь 2024

  use v5.40;
  try {
      my $result = load_and_process($file);
  }
  catch ($e) {
      warn "Pipeline error: $e";
  }
  finally {
      close_resources();   # runs whether or not an exception was thrown
  }

(Попробуйте::Tiny / Особенность::Compat::Try требуется только при нацеливании перлов старше 5,34.)

Долгосрочные характеристики (до 5.36)

Ссылки и закрытия первого класса – анонимные подписки, закрытия и эталонная конструкция являются фундаментальными и стабильными с Perl 5.

В сочетании с перламутр или плен для управления версиями и коробка для воспроизводимых снимков зависимостей современный проект Perl выглядит и выглядит как первоклассная разработка программного обеспечения.

Честные ограничения

Ни один случай для Перла не является полным без честности о том, где он падает:

Визуализация – Perl не имеет эквивалента ggplot2 или матрац. Для печати обычно требуется внешний вызов R, gnuplot или веб-библиотеки. Иногда эта слабость может стать реальной силой, позволяя использовать Perl5 в качестве языка приложения, который управляет и улучшает других участников.

Движение сообщества – сообщество науки о данных объединилось на Python и R. Найти готовые учебные пособия, ответы Stack Overflow и соавторов сложнее.

Ориентация объекта – без Moose/Moo модель OOP является вербальной; с ними она добавляет зависимость. Новый занятия функция может решить некоторые из этих проблем

Безопасность в масштабе – основной язык’s динамические скаляры делают большие, совместные числовые кодовые базы сложнее рассуждать (см. следующий раздел).


2. Система типа данных Perl – сильные стороны и ограничения кэша-эры

Типы базовых перфораторов

Перл’фундаментальная модель данных, основанная на трех конструкциях:

Построение Сигил Что это держит
Скаляр $ Одно значение: число, строка, ссылка или неопределённая
Массив @ Упорядоченный список скаляров, индексированный целым числом
Хеш % Незаказанная коллекция скалярных значений с ключом по строке

Все остальное – объекты, замки, сложные структуры данных – построено из этих трех примитивов с помощью ссылок (\@array, \%хеш, нижн.индекс { ... }).

Эта модель чрезвычайно гибкая. Один массив может содержать целые числа, числа с плавающей запятой, строки и вложенные ссылки одновременно. Именно эта гибкость сделала Перла доминирующим языком системного администрирования и веб-скриптов в течение двух десятилетий.

Проблема иерархии кэша

Современные ЦП достигают пиковой пропускной способности только при передаче данных через кэш L1/L2/L3 в больших, смежных блоках – свойство, называемое пространственной локальностью. Массивы Perl этого не предоставляют. Под капотом массив Perl представляет собой массив C из указателей для высокоразмещенного скаляра (ПС) структуры. Каждый скаляр содержит количество ссылок, тег типа и заполнение – обычно 24–56 байт на скаляр в 64-битной сборке. Таким образом, итерация более миллиона элементов массива Perl включает в себя миллионы ссылок, разбросанных по куче, создавая шаблон пропуска кэша, который полностью отрицает преимущество скорости современных трубопроводов SIMD.

Конкретное следствие: точечный продукт из двух 1 000-элементных векторов, написанных в чистом перле, примерно 100-1000× медленнее, чем эквивалентная операция на паре плавающих ndarrays PDL, которые занимают две плоские, 4 000-байтовые области памяти, которые удобно помещаются в кэш L1.

Контраст с R

R занимает любопытную середину. Как и Перл, это динамический, интерпретируемый язык – переменные – это нетипированные контейнеры, функции – первоклассные значения, а интерактивный REPL – основная среда разработки. R даже имеет прямые аналоги с Perl’s три основных типа:

Концепция Perl R аналог
$скаляр длина-1 атомный вектор или скаляр в списке
@array список()
%hash имя
Ссылка (\@arr) R не использует явные ссылки; вместо этого используется семантика копирования при изменении

Ноль R’s workhorse тип, т.е. атомный вектор не имеет прямого аналога Perl. Атомный вектор R – это непрерывный, однородно типизированный блок памяти – именно тот макет, который вознаграждает кэш процессора. Каждый встроенный скаляр в R на самом деле является атомным вектором длины-1; нет “скалярный” вне атомных векторов.

Этот выбор дизайна означает, что R-код естественным образом работает на векторах миллионов двойников с пропускной способностью уровня BLAS, без написания пользователем одного цикла или выделения специального “массив” объект.

R’Атомные типы:

Атомный тип Хранение C эквивалент
логический 4 байт/элемент интрига (с NA sentinel)
целое число 4 байт/элемент int32_t
удвоить 8 байт/элемент удвоить
комплекс 16 байт/элемент _Сложный двойной
характер указатель на CHARSXP символ * (внутренний)
необработанный 1 байт/элемент uint8_t

R также определяет структуры более высокого уровня, построенные на атомных векторах:

Урок: R’производительность вычислений при использовании в приложениях статистики и науки о данных поступает непосредственно из смежных атомных векторов. Перл’s эквивалентный путь к производительности является расширением (которое также является автономным) matlab например, окружающая среда), язык данных Perl PDL.


3. Введите PDL: сильно набитые N-мерные массивы

Perl Data Language (PDL, pdl.perl.org) расширяет Perl с ndarrays (N-мерные массивы): смежные, сильно типизированные буферы памяти, которые выглядят и чувствуют себя первоклассными объектами Perl.

use PDL;

# A 1-D float ndarray — 4 bytes × 5 elements in one contiguous block
my $v = float( 1.0, 2.0, 3.0, 4.0, 5.0 );

# A 128-dimensional random database of 1000 vectors — all in cache-friendly memory
my $db = random( 128, 1000 );   # double by default

# Dot product of every DB vector against a query — a single BLAS call
my $scores = $db x $query->transpose;

Типы примитивов PDL

PDL предоставляет полную палитру числовых типов C в качестве первоклассных конструкторов:

Тип PDL Байты Тип C Конструктор
байт 1 uint8_t байт(...)
короткий 2 int16_t короткий(...)
ushort 2 uint16_t рогоносец(...)
длинный 4 int32_t длинный(...)
инд 4 или 8 ssize_t Индекс(...)
длинный 8 int64_t длинный(...)
плавать 4 плавать плавать(...)
удвоить 8 удвоить двойной(...)
пла́вающий 8 _Комплексное плавание cfloat(...)
двойка 16 _Сложный двойной

Резьба и SIMD

Один из PDL’Наиболее отличительными особенностями являются *неявные потоки *: операции автоматически транслируются по дополнительным измерениям, устраняя явные циклы в пользовательском коде и делегируя внутренние циклы оптимизированным ядрам C или Fortran. В сочетании с set_autopthread_targ(N), PDL автоматически распараллеливает независимые срезы поперек N Потоки ОС – без записи пользователем одного отрастать или Поток::Очередь звоните.

Недопустимые значения

PDL имеет встроенную концепцию плохих значений (PDL::плохой), непосредственно аналогично R’с Н/Д. ndarray может быть помечен как “осведомленность о плохом значении”, и операции PDL правильно распространяют дефекты с помощью арифметики, статистики и ввода-вывода.


4. Сравнение типов: Perl, PDL и R бок о бок

В таблице ниже каждый часто используемый тип R сопоставляется с его ближайшими аналогами Perl и PDL, выделяя, где три языка согласуются, различаются или дополняют друг друга.

Тип R эквивалент Perl эквивалент PDL Заметки
удвоить (длина-1) $x = 3,14 (скалярный) двойной(3.14) – форма () R не имеет чистого скаляра; все является вектором
целое число (длина-1) $n = 42 (скалярный) длинные(42)
логический (длина-1) $flag = 1 / $flag = 0 байт(1) Перл использует правдивость; PDL использует 0/1 байт
удвоить вектор @arr = (1.1, 2.2, 3.3) двойной(1.1, 2.2, 3.3) PDL: непрерывный; @arr: массив указателей
целое число вектор @arr = (1, 2, 3) длинный(1, 2, 3)
логический вектор @flags = (1, 0, 1) байт(1, 0, 1)
комплекс вектор – (без встроенных) cdouble(...) Потребности Perl Математика::Комплекс; PDL имеет встроенную поддержку
характер вектор @strs = ('a','b') – (не числовой) PDL работает только с числами
необработанный вектор упаковка'C*', @bytes) байт(...)
Н/Д неопределённая Неверное значение в ndarray Плохие значения PDL распространяются, как R’с Н/Д
NULL неопределённая в контексте списка
список @array или ссылка \@array
имя список %hash или \%хеш
матрица (2-D) массив массивов @aoa 2D ndarray pdl()[[...],[...]]) PDL: основной столбец; R: основной столбец
массив (N-D) вложенные ссылки N-D ndarray $x->обновить(...)
data.frame %hash из @arrays 2-D ndarray (числовые столбцы) + Perl хэш (смешанный) Нет однозначных карт типа PDL
фактор таблица поиска хеша + @indices длинный Ндаррей + Перл @levels массив
окружающая среда %hash или пространство имен пакета
вечеринка / закрытие нижн.индекс { ... } / закрытие PDL PP определяет скомпилированные ядра
S3 / S4 объект блаженная ссылка + метод диспетчеризации Объект PDL (блаженный ndarray) Объекты PDL являются первоклассными объектами Perl

Основные выводы

Таким образом, комбинация Perl+PDL обеспечивает союз того, что R предлагает в качестве статистического языка, и того, что Perl предлагает в качестве системного языка – за счет более крутой кривой обучения и менее готового, откровенно ограниченного статистического инструментария.

Однако комбинация Perl+PDL+R (при этом последний используется как компонент, или инструментализированный через Perl)


5. Дорожная карта: что покрывает остальная часть этой серии

В этой серии описывается создание векторного ядра базы данных, встроенного в Perl5 + PDL с нуля. Векторные базы данных лежат в основе современных конвейеров генерации с расширенным извлечением (RAG), семантического поиска и систем рекомендаций ближайших соседей. Внедрение одного из первых принципов является отличным средством для демонстрации PDL’числовые возможности вместе с Perl’сильных сторон систем-программирования.

Каталог, совместно разработанный вместе с этими сообщениями, содержит следующие компоненты, каждый из которых будет предметом одного или нескольких выделенных сообщений, которые будут ссылаться на файлы в выделенном репозитории.

Post 1 – Сериализация и ввод-вывод: VectorIO модуль

Файл: VectorIO.pm

Двигатель хранит векторы как упакованные бинарные blobs внутри MessagePack полезные нагрузки. Эта статья охватывает:

Post 2 – Моделирование векторной базы данных

Файл: simulate_vectorDB.pl

Прежде чем искать базу данных, нужно ее выполнить. Это сообщение показывает:

Post 3 – Бенчмаркинг: The timing_DB Модуль

Файл: timing_DB.pm

Требования к исполнению требуют измерения. Эта статья представляет:

Post 4 – Кластеризация K-средств с PDL::Статы::Kmeans

Файл: kmeans.pl

Кластеризация K-средних – это основа подхода инвертированного индекса (IVF) к приближенному поиску ближайших соседей. Эта статья охватывает:

Post 5 – Мини-пакетные K-средства: масштабирование до больших наборов данных

Файл: compare_kmeans_centroids.pl

Для полного k-средства требуются все данные в памяти для каждой итерации. Mini-batch k-means торгует небольшим количеством центроидной точности для значительного сокращения объема памяти и вычислительных ресурсов. Этот пост исследует:

Post 6 – Поиск инвертированных файлов (IVF)

Файл: compare_ivf_search.pl

С центроидами в руке мы можем разбить базу данных и выполнить подлинейный приблизительный поиск ближайшего соседа. Эта статья охватывает:

Post 7 – Проверка против R: Численная правильность и межязыковые трубопроводы

Файлы: compare_kmeans_centroids.R, compare_kmeans_centroids_pure.R, plot_centroid_coordinates.R

Последний пост в серии фундаментов закрывает петлю между Perl и R:


Далее – Сообщение 1: Сериализация и ввод-вывод с VectorIO.pm


Современные ЦП имеют несколько уровней быстрой встроенной памяти под названием cache (L1, L2, L3), которые находятся между ядрами процессора и основной оперативной памятью. L1 является самым маленьким (обычно 32–64 КБ на ядро) и самым быстрым (задержка 1–4 часовых циклов); L2 больше (256 КБ–1 МБ) и немного медленнее; L3 делится между ядрами (4–64 МБ) с более высокой задержкой. Основная оперативная память находится дальше с задержкой 60–100 нс – примерно в 200 раз медленнее, чем L1.

Когда вычисление затрагивает память в предсказуемом, непрерывном шаблоне, аппаратная программа prefetcher может загрузить предстоящие данные в L1/L2 до того, как это потребуется, обеспечивая почти пиковую пропускную способность. Разрозненная погоня за указателями (например, обход массива Perl с распределенными по куче скалярами) побеждает предварительную выборку, останавливая процессор, пока он ожидает, что каждый недостаток кэша будет разрешен из оперативной памяти.