最近訪れたサイト
最近訪れたサイト

データ・サイエンス言語としてのPerl5

[終了] 最終更新日 によって Joe Schaefer 日, 14 6月 2026    ソース
 

データ・サイエンス

シリーズ紹介 —Post 0 of N
この投稿は、Perl5 + PDLで完全に記述されたベクトルデータベースエンジン(VDBE)の共同開発を文書化したシリーズの最初の投稿です。後の投稿は、そのエンジンのすべてのコンポーネントを通過します。これはステージを設定します。このシリーズの主な推進力は、パフォーマンス請求を行わないので、VDBEをダンプさせることではなく、他の言語で達成できるほぼすべてのことを達成するためにPerlをどのように使用するかを示すことですが、よりスマートです!


1. データ・サイエンスにPerl5を使用する理由

データ・サイエンティストが言語の選択について話し合うと、会話はPython、RまたはJuliaにすばやく収束します。Perl5は、テーブルに座ることはめったにありませんが、2番目の外観に値する魅力的な一連の特性を持ちます。これらの特性は、長年にわたって実質的に変化していません(Perl5は常にこのようになりました)。言語に触れられ、その地形、合理性、柔軟性、表現可能性を高く評価することを学び、実際にあなたの仕事を前進させるためにそれを使用していない限り、これらの機能はPerl5で無料になるだけでなく、プロジェクトを前進させるのに役立ちます.

ユビキティとゼロインストールの展開

Perl5は、ほぼすべてのUNIX系オペレーティング・システムのデフォルト・コンポーネントとして出荷されます。Linuxディストリビューション、macOS、BSD、および多くの組込みLinux環境はすべて動作しています。perl Binary Out Of The BoxシングルここでPythonが始まっていますが、Perlが存在し、完全なPythonスタックが存在しないヘッドレスサーバー、ネットワークアプライアンス、またはHPCログインノードを見つけることは一般的です。Perlに書き込まれたデータ・パイプラインは、conda 環境、A venvまたはコンテナ。

データ・センターからエッジへの移植性

256コアのHPCノード上のテラバイト・データセットを分析するのと同じスクリプトで、構成の変更が少ない場合は、Raspberry Pi、IoTゲートウェイまたは組込みコントローラで実行できます。Perlの単一バイナリ・デプロイメント・モデルと実行時のオーバーヘッドが低いため、”一度書けば、どこでも実行できる” PythonのインタプリタのオーバーヘッドまたはJuliaのJITウォームアップ時間が許容できない環境での言語。

どこにでもデプロイする場合は、everywhere Perl5を選択します。

テキストとデータ管理に基づく遺産

Perlは、テキスト処理、正規表現、および”アドヒーシブ” システム・コンポーネント間の作業。実際、科学的データ・パイプラインは数値計算ではなく、異種ファイル形式の読取り、乱雑なレコードのクリーニング、異なるソースからデータセットを結合し、結果をダウンストリーム消費コンポーネントにルーティングするというデータ・ラングリングによって支配されています。

Perlの正規表現エンジンは最も強力なものの1つであり、1つのライナーは、他の言語のヘルパー・ライブラリを必要とするデータ・クレンジング・タスクを実行できます。

あなたが科学コンピューティングの領域にいるならば、あなたはワークフロー管理システム再現可能な研究の概念に遭遇したかもしれません。どちらも、エンドツーエンドのデータ変換とワークフローの実行に依存して、アナリストや科学者がそれぞれデータをインサイトや推論に変えるために行う必要のある、手作業でエラーが発生しやすい、面倒なポイントやクリック・アクティビティを排除します。

この勇敢な新しい世界では、Perl5の豊富な履歴により、ワークフローのコンポーネントとして、またはこれらのワークフローを実装するアプリケーション言語として、両方を輝かせることができます。

CPAN: テスト済みのモジュール・エコシステム

Comprehensive Perl Archive Network(CPAN)は、想像できるすべてのドメインで200,000を超えるモジュールをホストします。データ・サイエンスの提供はPythonほど広範囲ではありませんが、専用ビルダーの基本的なコンポーネントは次のとおりです。

  • PDL (Perl Data Language)— 強く型付けされたN次元配列を持つベクトル化された数値計算(以下で詳しく説明します)。

  • PDL::Stats—PDL ndarrays上に構築された記述統計、回帰、クラスタリング(k-means、ミニバッチk-means)など。

  • AI::MXNetAI::TensorFlow— ディープ・ラーニング・バインディング。

  • Statistics::RegressionStatistics::Descriptive—PDL依存性がないクラシック統計。

  • テキスト::CSVスプレッドシート::XLSXデータ::MessagePackシリアル - 高パフォーマンスのシリアライズおよびI/O。

  • DBI +多数のデータベース・ドライバ — すべての主要なRDBMSへのSQLアクセス。

  • MCE (多コア・エンジン)— 共有および分散メモリー・ワークロードの構造化並列化。

  • Inline::CInline::CPP—CまたはC++コードをPerlソース・ファイルに直接埋め込みます。コンパイラは、スクリプトが初めて実行されたときに透過的に起動されるため、完全なXSビルド・システムを使用せずに、パフォーマンス・クリティカルなカーネルをその他の純粋なPerlプログラムにドロップするのは簡単です。

  • FFI::Platypus— 任意の共有ライブラリの関数を呼び出す(.so / .dylib / .dll) XSまたはCの接着コードの単一行を書かずにPerlから。Platypusは、Cと同等の型、構造体、コールバック、およびクロージャをすべてサポートしており、PerlをBLAS、LAPACK、HDF5またはその他のネイティブ・ライブラリにバインドする最新の方法です。

モダン・ペルはおじいちゃんのパールではない

以下の機能は、公式リリースノート(perl5360delta, perl5380delta, perl5400delta)と、安定ステータスに達したか、最初に導入されたリリースによって編成されます。データサイエンスおよび科学計算ワークロードに関連する機能のみが強調表示されます。

Perl 5.36—2022年5月

  • **use v5.36**— 機能バンドルが自動的に有効になりましたuse warnings その上use strict。また、無効化されます。indirect method-callの構文とmultidimensional ハッシュキーシミュレーション。微妙なバグの2つの一般的なソースを排除します。

  • 名前付きサブルーチン署名 *(5.36以降は安定、5.20以降は実験的)*— 関数のパラメータは、オプションのデフォルトで名前で宣言されるようになりました。▲//= および||= default-value演算子はさらに5.38の署名に追加され、undef または、それぞれ虚偽:

  use v5.36;
  sub clamp ($val, $lo = 0, $hi //= 1) {
      $val < $lo ? $lo : $val > $hi ? $hi : $val;
  }
  • isa class-instance演算子 *(5.36以降安定、5.32で導入)*— $obj isa "ClassName" 次の値よりクリーンなブール値を返しますref($obj) eq "ClassName".

  • builtin module *(stable since 5.40; experiment since 5.36)*— 字句的に読み込み可能な関数がインタプリタに直接組み込まれています。安定した5.40バンドルには、特に次のものが含まれます。

  • ceil, floor — 整数丸めなしuse POSIX.

    • trim — 文字列から先頭/末尾の空白を削除します。
    • indexed - 各要素をインデックスとペアにします。for ループ(以下を参照)。
    • true, false, is_bool — 型付きブールセンチネル; シリアライザがJSONを生成できるようになりましたtrue/false というより1/0.
    • weaken, unweaken, is_weak — メモリーリークのない双方向データ構造体を構築するための参照カウント制御。
    • blessed, reftype, refaddr - 参照イントロスペクション。
  • 安定したブール追跡 *(5.36)*— ブールとして作成されたスカラー(例: !!1)は、代入を通じてブール性を保持するようになり、JSONおよびMessagePackへの信頼できる型認識シリアライズが可能になります。

  • 複数値for loops *(stable since 5.40; experiment since 5.36)*手動でインデックス演算を行わずにペアまたはNタプルを反復する:

  use v5.40;
  use builtin 'indexed';

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

または複数の値を同時に取得します。

  use v5.40;

for my ($val1, $val2, $val3) (@scores)  { ... }
  • defer blocks *(experimental since 5.36)*— ブロックが通常または例外を問わず、無条件にクリーンアップ・コードを実行するスコープ終了ガード。デストラクタベースのスコープガード・オブジェクトの自然な置換であり、データ・パイプラインでのリソース管理のための重要なパターンです。

Perl 5.38—2023年7月

  • PERL_RAND_SEED 環境変数 *(5.38)*— 実行前にこの変数を設定すると、rand コール(明示なし) srand)は同じシーケンスを生成し、ソース・コードを変更せずに再現可能確率アルゴリズム(シミュレーション、ランダム・サンプリング、モンテカルロ・メソッド)を有効にします。

  • class / field / method syntax *(experimental since 5.38)*— どちらも必要ない、専用の字句スコープのオブジェクトシステムbless なし@ISA CPANモジュールもありません。データセット行、モデル・パラメータ、パイプライン・ステージなどの型付き値オブジェクトを定義する場合に役立ちます。

  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

Perl 5.40—2024年6月

  • try / catch 例外処理 *(5.40以降安定、5.34以降実験) finally block added in 5.36)*— 構造化例外処理がコア言語機能になりました。CPANモジュールは必要ありません。
  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
  }

(Try::Tiny / Feature::Compat::Try 5.34より古いperlsをターゲティングする場合にのみ必要です。)

  • 複数値for loops *(stable since 5.40)*— 上記の5.36エントリを参照; 彼らはこのリリースで実験から安定に卒業しました。

  • builtin::inf およびbuiltin::nan *(5.40以降の実験値)*— 型付き浮動小数点無限大および非数値定数、消去9**9**9 POSIXは数値コードでハッキングします。

  • ^^ logical XOR operator *(5.40)*— 中優先論理演算子セットを完了します(&&, ||, ^^); ブールマスク操作に便利です。

  • use v5.40 組み込み関数をインポート— 機能バンドルを有効にする以外に、use v5.40 対応するものもインポートします。builtin バージョンバンドル、すべての安定したbuiltin:: 個別の名前のない短縮名として使用できる関数use builtin 文。

長年の機能(5.36以前)

  • say およびstate *(5.10以降)*— say 次であるprint 暗黙の復帰改行state 包含サブ(軽量メモリプリミティブ)の呼出し間で永続する字句を宣言します。

  • ファーストクラスの参照と閉鎖 - 匿名のサブ、閉鎖、参照構造は基本であり、Perl 5以来安定しています。

  • **use constant**またはCPAN Readonly 指定された定数のモジュールReadonly 深い不変性を、use constant できません。

結合perlbrew またはplenv バージョン管理とcarton 再現可能な依存性スナップショットの場合、最新のPerlプロジェクトは、一流のソフトウェア・エンジニアリング作業のように見えて感じます。

正直な制限

No case for Perl is complete without honesty about where it falls short:

  • 可視化—Perlは同等ではありませんggplot2 またはmatplotlib。通常、プロットには、R、gnuplot、またはWebライブラリへの外部コールが必要です。この弱点が実際の強みになる場合があり、他のアクターを編成および拡張するアプリケーション言語としてPerl5を使用できます。

  • コミュニティの勢い - データサイエンスコミュニティがPythonとRに集約されました。既製のチュートリアル、スタックオーバーフローの回答、および共著者の検索はより困難です。

  • オブジェクトの向き - Moose/Mooを使用しない場合、OOPモデルは冗長で、依存関係が追加されます。新しいclass 機能はこれらの問題を解決するかもしれません

  • Type safety at scale— コア言語の動的スカラーは、大規模で協調的な数値コードベースを推論しにくくします(次の項を参照)。


2.Perlデータ型システム — 長所とキャッシュ時代の限界

コアPerlタイプ

Perlの基本的なデータ・モデルは、次の3つの構成に基づいています。

「Construct」Sigil「What It Holds」
|———–|——-|—————|
| スカラー $ |単一の値: number、string、reference、またはundef |
アレイ @ |整数で索引付けされたスカラーの順序付きリスト|
ハッシュ % |文字列がキーとなるスカラー値の順序なしコレクション|

他のすべてのもの(オブジェクト、クローズ、複雑なデータ構造)は、これらの3つのプリミティブからreferencesを介して構築されます。\@array, \%hash, sub { ... }).

このモデルは非常に柔軟です。1つの配列で、整数、浮動小数点数、文字列およびネストされた参照を同時に保持できます。こうした柔軟性こそが、ペルが二十年にわたって支配的なシステム管理とウェブスクリプティング言語になったのである。

キャッシュ階層の問題

最新のCPUは、データがL1/L2/L3キャッシュを流れる場合にのみ、ピーク・スループットを実現します。 大規模で連続するブロック- spatial localityと呼ばれるプロパティPerl配列はこれを提供しません。フードの下では、Perl配列は、ヒープ割当てスカラーへのポインタのC配列です(SV)構造。各スカラーには、参照カウント、型タグ、およびパディング(通常は64ビット構築のスカラーあたり24 - 56バイト)が格納されます。したがって、100万要素以上のPerl配列を反復するには、ヒープ全体に散在する100万ポインタ間接参照が必要であり、最新のSIMDパイプラインの速度優位性を完全に否定するキャッシュミス・パターンが生成されます。

A concrete consequence: 純粋なPerlで記述された2つの1 000要素ベクトルのドット積は、L1キャッシュに快適に収まる2つのフラットな4 000バイトのメモリー領域を占めるPDLフロートndarraysのペアに対する同等の操作より、およそ100–1000×低速です。

Rとの対比

Rは好奇心旺盛な中盤。Perlと同様に、動的で解釈された言語です。変数は型付けされていないコンテナで、関数はファーストクラスの値で、対話型REPLは主要な開発環境です。Rは、Perlの3つのコア・タイプに直接類似しています。

Perlコンセプト Rアナログ
$scalar length-1原子ベクトルまたはスカラーインリスト
@array list()
%hash 名前付きlist()
リファレンス(\@arr) Rは明示的な参照を使用しません。代わりにcopy-on-modifyセマンティクスを使用します

ただし、Rのworkhorse型、つまり原子ベクトルには、対応する単純なPerlはありません。Rアトミック・ベクトルは、連続的で均質に型付けされたメモリー・ブロックであり、まさにCPUキャッシュが与えるレイアウトです。Rのすべての組込みスカラーは、実際にはlength-1原子ベクトルです。”ベアスカラー” 原子ベクトルの外

この設計の選択は、ユーザーが単一のループを記述したり特別なループを割り当てたりすることなく、RコードがBLASレベルのスループットで数百万倍ものベクトルに対して自然に動作することを意味します。”配列” オブジェクト。

Rの原子型は次のとおりです。

Rアトミック型 ストレージ C相当
logical 4バイト/要素 int (´・ω・`)
integer 4バイト/要素 int32_t
double 8バイト/要素 double
complex 16バイト/要素 _Complex double
character CHARSXPへのポインタ char * (インターネット)
raw 1バイト/要素 uint8_t

R also defines higher-level structures built on atomic vectors:

  • matrix—a 2-D原子ベクトルdim 属性。
  • アレイ—N-D原子ベクトルdim 属性。
  • data.frame— 等長原子ベクトルの名前付きリスト。
    Rの表形式データ。
  • factor— 整数ベクトルlevels 属性; 質的データをエンコードします。

The lesson: 統計およびデータ・サイエンス・アプリケーションで使用されるRのコンピューティング・パフォーマンスは、その連続した原子ベクトルから直接流れます。Perlのパフォーマンスへの同等のパスは拡張です(これはスタンドアロンでもある)。matlab 例えば、Perl Data Language 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 exposes the full palette of C numeric types as first-class constructors:

PDLタイプ バイト Cタイプ コンストラクタ
byte 1 uint8_t byte(...)
short 2 int16_t short(...)
ushort 2 uint16_t ushort(...)
long 4 int32_t long(...)
indx 4か8かssize_t indx(...)
longlong 8 int64_t longlong(...)
float 4 float float(...)
double 8 double double(...)
cfloat 8 _Complex float cfloat(...)
cdouble 16 _Complex double cdouble(...)

スレッドとSIMD

PDLの最も特徴的な機能の1つは暗黙的なスレッドです: 操作は余分な次元で自動的にブロードキャストされ、ユーザー・コードの明示的なループがなくなり、内部ループが最適化されたCまたはFortranカーネルに委任されます。結合set_autopthread_targ(N)、PDLは自動的に独立したスライスを平行にしますN OSスレッド — ユーザーが1つも書かずにfork またはThread::Queue コール。

不正な値

PDLには、bad valuesという概念が組み込まれています。PDL::Bad(Rとほぼ同じ) NA。ndarrayは次のようにフラグ付けできます。”誤値認識”、およびPDL操作は、算術、統計、およびI/Oによって正しく悪さを伝播します。


4. タイプ比較: Perl、PDL、Rサイドバイサイド

次の表は、一般的に使用されるすべてのR型を最も近いPerlとPDLの対応型にマップし、3つの言語が互いに一致、異なる、または補完している箇所を強調しています。

| |
|—|—|—|—|

主なポイント

  • 純粋な数値、均質データ(ベクトル、マトリックス、テンソル)の場合、PDL ndarraysおよびR原子ベクトルは機能的に同等であり、同等に効率的です。

  • 異種表形式データ (混合型、文字列列、ファクタ)、Rの場合data.frame より人間工学的です。Perlは通常、配列のハッシュまたは次のような専用モジュールを使用します。Data::Frame またはPDL::IO::CSV.

  • テキスト、不規則構造、システム接着の場合、Perlのネイティブ型はRとPythonの両方よりも優れています。

  • したがって、Perl+PDLの組み合わせは、Rが統計言語として提供するものと、Perlがシステム言語として提供するもののunionを、急激な学習曲線と、すぐに使用できるND率直に限られた統計ツールのコストで提供します。

ただし、Perl+PDL+Rの組合せ(後者がコンポーネントとして使用されている場合、またはインストゥルメンタル Perlより)


5. ロードマップ: このシリーズの残りは何をカバー

このシリーズでは、Perl5 + PDLでゼロから構築されたベクトル・データベース・エンジンの構築について説明します。ベクトル・データベースは、最新の検索拡張生成(RAG)パイプライン、セマンティック検索、および最も近い推奨システムを支えています。最初の原則から1つを実装することは、Perlのシステムプログラミングの強みとともにPDLの数値機能を実証するための優れた手段です。

これらの投稿とともに共同開発されるディレクトリには、次のコンポーネントが含まれています。各コンポーネントは、専用リポジトリ内のファイルを参照する1つ以上の専用投稿の対象となります。

Post 1— シリアライズとI/O: VectorIO モジュール

ファイル: VectorIO.pm

エンジンはベクトルをパックされたバイナリBLOBとして内部に格納しますMessagePack ペイロード。この記事の内容:

  • クリーンなモジュールを設計するExporter- ベースのパブリックAPI use v5.40.
  • システム境界でスキーマの正確性を強制する検証ヘルパー。

Post 2— ベクトル・データベースのシミュレート

ファイル: simulate_vectorDB.pl

データベースを検索する前に、データベースが必要です。この記事では、次の内容を示します。

  • 再現可能なランダムフロートベクトルの生成PDL::random.
  • 使用GetOpt::Long 人間工学的なCLIオプション解析用。
  • 書き込みA --seed- 複数の実行で同一のデータベースを生成する制御シミュレーション- ベンチマークに不可欠です。

Post 3 - ベンチマーク: timing_DB モジュール

ファイル: timing_DB.pm

パフォーマンス要求には測定が必要です。この記事では、次のことを紹介します。

  • 再利用可能なパールベンチマーキングハーネスTime::HiRes.
  • Perl/PDLとR実装間の公正な壁時計比較の方法論。
  • 異なるワークロード・サイズのスループット(ベクトル/秒)とレイテンシ(ミリ秒/問合せ)の解釈。

Post 4—K-MeansクラスタリングPDL::Stats::Kmeans

ファイル: kmeans.pl

K-meansクラスタリングは、近似近傍検索に対する逆ファイル索引(IVF)アプローチのバックボーンです。この記事の内容:

『THE PDL::Stats::Kmeans インタフェースとその返品契約(centroid, cluster, n, R2, ss).

  • 解釈[obs × clusters] 返されたメンバーシップ・マスクrun_kmeans.
  • Perl/PDL k-meansのセントロイドをRと比較するkmeans() およびClusterR::MiniBatchKmeans() 数値の正確性を検証します。

Post 5— ミニバッチK-Means: 大規模なデータセットへのスケーリング

ファイル: compare_kmeans_centroids.pl

完全なk-meansでは、反復ごとにメモリー内のすべてのデータが必要です。ミニバッチk-meansは、メモリと計算を大幅に削減するために、少量の重心精度を取引します。この記事では、次の点を調査します。

  • PDLで真の再サンプリングされたミニバッチループを実装する。
  • フルバッチバリアントとミニバッチバリアントの間の重心ドリフト。
  • Rの並べて出力MiniBatchKmeans からClusterR パッケージ。

Post 6 - Inverted File Index(IVF)検索

ファイル: compare_ivf_search.pl

セントロイドを手元に置いて、データベースを分割し、近傍近傍サブリニア検索を実行できます。この記事の内容:

  • Building the inverted lists: 各データベース・ベクトルを最も近い重心にマップします。
    『THE unpack_inverted_lists ヘルパーVectorIO.
  • Querying: 最上位Kの最寄りのセントロイドを見つけ、それらのリストのみを検索します。
  • プローブされたリストの数が異なるため、精度と速度のトレードオフが異なります。

Post 7 - Rに対する検証: 数値的正確性と言語間パイプライン

ファイル: compare_kmeans_centroids.R, compare_kmeans_centroids_pure.R, plot_centroid_coordinates.R

The final post in the foundation series closes the loop between Perl and R:

  • PDLの結果をCSVにエクスポートし、独立した検証のためにRで読み取ります。
  • ggplot2を使用して、両方の言語の重心座標を同時に視覚化します。
  • ワークフロー・パターン”Perlでの計算、Rでの可視化” 両生態系の強みを活かしています。

**Next up—Post 1:**シリアライズとI/O VectorIO.pm


最新のCPUには、プロセッサ・コアとメインRAMの間に位置するcaches (L1、L2、L3)と呼ばれる、高速なオンチップ・メモリーが複数レベルあります。L1は、最小(通常はコア当たり32–64KB)で最速(1–4クロック・サイクル・レイテンシ)です。L2は大きく(256KB–1MB)、わずかに遅くなります。L3は、より高いレイテンシでコア(4–64MB)間で共有されます。メインRAMは、60から100 nsのレイテンシ(L1より約200×遅い)でさらに離れています。

計算が予測可能な連続したパターンでメモリーに接触すると、ハードウェアprefetcherは、必要になる前に今後のデータをL1/L2にロードできるため、ピークに近いスループットを実現できます。分散ポインタチェーシング(ヒープ割り当てスカラーのPerl配列のトラバースなど)はプリフェッチを破り、各キャッシュミスがRAMから解決されるのを待機しながらCPUをストールします。