In computing, single program, multiple data (SPMD) is a term that has been used to refer to computational models for exploiting parallelism whereby multiple processors cooperate in the execution of a program in order to obtain results faster.
The term SPMD was introduced in 1983 and was used to denote two different computational models:
The (IBM) SPMD is the most common style of parallel programming and can be considered a subcategory of MIMD in that it refers to MIMD execution of a given ("single") program.[7] It is also a prerequisite for research concepts such as active messages and distributed shared memory.
In SPMD parallel execution, multiple autonomous processors simultaneously execute the same program at independent points, rather than in the lockstep that SIMD or SIMT imposes on different data. In SIMD the same operation (instruction) is applied on multiple data to manipulate data streams (a version of SIMD is vector processing where the data are organized as vectors).
Unlike SIMD, SPMD does not require special support from the processor it's run on, be it CPUs or GPUs.
SPMD and SIMD are not mutually exclusive: each SPMD program can include SIMD, or vector, or GPU sub-processing. Many CPUs include multiple SIMD-capable cores, each of which can participate in SPMD; the same applies to many GPUs containing several SIMD "streams". SPMD has been used for parallel programming of both message passing and shared-memory machine architectures.
On distributed memory computer architectures, SPMD implementations usually employ message passing programming. A distributed memory computer consists of a collection of interconnected, independent computers, called nodes. For parallel execution, each node starts its own program and communicates with other nodes by sending and receiving messages, calling send/receive routines for that purpose. Other parallelization directives such as Barriersynchronization may also be implemented by messages. The messages can be sent by a number of communication mechanisms, such as TCP/IP over Ethernet, or specialized high-speed interconnects such as InfiniBand or Omni-Path. For distributed memory environments, serial sections of the program can be implemented by identical computation of the serial section on all nodes rather than computing the result on one node and sending it to the others, if that improves performance by reducing communication overhead.
Nowadays, the programmer is isolated from the details of the message passing by standard interfaces, such as PVM and MPI.
Distributed memory is the programming style used on parallel supercomputers from homegrown Beowulf clusters to the largest clusters on the Teragrid, as well as present GPU-based supercomputers.
共有メモリマシン(複数のCPUが相互接続され、同じメモリ空間にアクセスするコンピュータ)では、共有は物理的に共有されたメモリ、または論理的に共有された(ただし物理的に分散された)メモリのいずれかのコンテキストで実装できます。共有メモリに加えて、コンピュータシステムのCPUはローカル(またはプライベート)メモリも持つことができます。これらのいずれのコンテキストにおいても、同期はハードウェアで有効化されたプリミティブ (比較交換やフェッチ追加など) を使用して有効化できます。このようなハードウェアサポートがないマシンでは、ロックを使用して、共有可能なデータを共有メモリ領域に格納することにより、プロセッサ間 (またはより一般的にはプロセスやスレッド間) でデータを「交換」できます。ハードウェアが共有メモリをサポートしていない場合、データを「メッセージ」としてパックすることが、物理メモリがプロセッサにローカルであり、他のプロセッサのメモリへのアクセスに時間がかかる多数のプロセッサを持つ共有メモリ コンピュータを (論理的に) プログラムする最も効率的な方法となることがよくあります。共有メモリ マシン上の SPMD は、標準プロセス (ヘビーウェイト) またはスレッド (ライトウェイト) で実装できます。
共有メモリマルチプロセッシング(対称型マルチプロセッシング(SMP)と非均一メモリアクセス(NUMA)の両方)は、プログラマに共通のメモリ空間と実行の並列化の可能性を提供します。IBMのSPMDモデルでは、連携するプロセッサ(またはプロセス)は、並列ディレクティブ(並列化および同期ディレクティブ。共有メモリ同期変数に対する比較交換およびフェッチ追加操作を利用できます)を使用してプログラム内で異なるパスをたどり、共有メモリ内のデータ(「共有データ」)に対して操作を実行します。プロセッサ(またはプロセス)は、ローカルメモリ内のデータ(「プライベートデータ」)にもアクセスして操作を実行できます。これに対し、フォークアンドジョイン方式では、プログラムは1つのプロセッサで実行を開始し、並列ディレクティブが検出されると実行が並列領域に分割されます。並列領域では、プロセッサは異なるデータに対して並列タスクを実行します。典型的な例は並列DOループで、異なるプロセッサがループに関係する配列の別々の部分を処理します。ループの最後に、実行は同期され(ソフトバリアまたはハードバリア[ 6 ]を使用)、プロセッサ(プロセス)は実行可能なプログラムの次のセクションに進みます。 (IBM) SPMDは、共有メモリマルチプロセッシングの現在の標準インターフェースであるOpenMPで実装されており、通常はスレッドと呼ばれる軽量プロセスによって実装されるマルチスレッドを使用します。
Current computers allow exploiting many parallel modes at the same time for maximum combined effect. A distributed memory program using MPI may run on a collection of nodes. Each node may be a shared memory computer and execute in parallel on multiple CPUs using OpenMP. Within each CPU, SIMD vector instructions (usually generated automatically by the compiler) and superscalar instruction execution (usually handled transparently by the CPU itself), such as pipelining and the use of multiple parallel functional units, are used for maximum single CPU speed.
MPI is commonly used to implement SPMD. As mentioned earlier it is suited for distributed memory systems (multiple machines) but also works on shared-memory scenarios (multiple cores).[9]
Most graphics shaders are written in a SPMD programming model: the code describes an operation on a single element. The code is then turned into parallel code by the shader compiler using whatever parallelism facilities the hardware offers (multiple units of SIMD in the case of most GPUs, multiple units of SIMT in the case of Nvidia GPUs). CUDA likewise follows an SPMD/SIMT model.[10] When targeting SIMD hardware, control flow is typically mapped onto SIMD operations by predication, which restricts what portions of a vector register is changed using a mask.[11][12] GPUs generally do not have a unified address space; instead, there are several levels of memory available, only some of which are shared among shader programs.[13]
In the machine learning libraries Jax and PyTorch, SPMD is used to distribute the work (shard) over multiple devices, either automatically or manually.[14][15] By having all devices run what is functionally the same program, automatic work distribution becomes much easier and the need for cross-device communication is reduced.[16]
Clang offers an SPMD code-generation mode for its OpenMP offloading support in addition to the regular mode.[17][18] Clang's OpenCL part considers a target to be SPMD if the hardware is able to spawn multiple work-items on-the-fly.[19]
Intel IPSC (Implicit SPMD Program Compiler) は、C の方言で書かれた SPMD プログラム用のオープンソース コンパイラです。一見シングル スレッドの SPMD モデルで書かれた入力プログラムを、効率的な x86 (SSE2 から AVX512) または ARM (NEON) SIMD コード、または Intel GPU SIMD コードに変換します。[ 11 ] IPSC の大部分は Matt Pharr によって書かれました。彼によると、IPSC はLarrabeeのようなアーキテクチャ向けに優れたワイド ベクトル コードを生成するコンパイラを作成するために設計されました。自動ベクトル化は信頼性を持って使用するには脆弱すぎることが判明し、シェーダーのようなソリューションが求められました。[ 10 ] [ 12 ]
NSIMDライブラリは、概念的にはIPSCと同様のSPMDインターフェースを提供します。スカラー、x86(SSE2からAVX-512)SIMD、ARM(NEONまたはSVE)SIMD、POWERPC VMX/VSX SIMD、CUDA、ROCm、およびOneAPIを対象としています。[ 20 ]
SPMD-on-SIMD(IPSCに類似)はLLVM上で学術的に実証されているが、[ 21 ] [ 22 ] 2026年3月現在、公式LLVMには採用されていない。
「Single-Program Multiple-Data」の頭文字をとったSPMDという略語は、並列コンピューティングを活用するための2つの異なる計算モデルを説明するために使用されており、これは両方の用語がフリンの分類法の自然な拡張であるためです。[ 7 ]それぞれの研究者グループは、並列プログラミングの異なるモデルを独立して説明するためにSPMDという用語を互いに使用していたことを知りませんでした。
SPMDという用語は、1983年にミシェル・オーガン(ニース・ソフィア・アンティポリス大学)とフランソワ・ラルベイ(トムソン/シントラ)によって、OPSILA並列コンピュータの文脈、およびフォークアンドジョインとデータ並列計算モデルのアプローチの文脈で初めて提案されました。[ 1 ]このコンピュータは、マスター(コントローラプロセッサ)とSIMDプロセッサ(またはフリンが提案したベクトルプロセッサモード)で構成されていました。オーガンのSPMDモデルでは、同じ(並列)タスク(「同じプログラム」)が、データベクトルの一部(「スライス」)に対して動作する異なる(SIMD)プロセッサ(「ロックステップモードで動作」[ 1 ])で実行されます 。具体的には、彼らの1985年の論文[ 2 ]および他の論文[ 3 ] [ 1 ]では、次のように述べられています。
ここでは、SPMD(シングルプログラム、マルチデータ)動作モードについて考察します。このモードでは、同じタスクを(プロセッサごとに1つずつ)同時に実行できますが、プロセッサ間のデータ交換はできません。データ交換は、SIMDモードでのみベクトル代入によって行われます。同期処理は、グローバルなフォークジョインプリミティブを使用してSIMDモードとSPMDモードを切り替えることで行われると想定します。
ほぼ同時期(1983 年後半から 1984 年初頭)に、当時 IBM に所属し RP3 グループの一員であった Frederica Darema が、彼女が提案した別の SPMD 計算モデルを定義するために SPMD という用語を提案しました。[ 6 ] [ 5 ] [ 4 ]このプログラミング モデルは、その後、幅広い汎用高性能コンピュータ (512 プロセッサの IBM Research Parallel Processor Prototype である RP3 を含む) に適用され、現在の並列コンピューティング標準につながりました。 (IBM) SPMD プログラミング モデルは、協調して動作する複数のプロセッサを想定しており、すべて同じプログラムを実行しますが、プログラムに埋め込まれた並列化ディレクティブに基づいて、プログラム内の異なるパスをたどることができます。[ 6 ] [ 5 ] [ 4 ] [ 23 ] [ 24 ]
並列計算に参加するすべてのプロセスは実行の開始時に作成され、終了まで存続します。プロセッサ/プロセスは異なる命令を実行し、異なるデータに対して処理を行います。各プロセスが行うべき作業は動的に割り当てられます。つまり、プロセスは異なる命令を実行し、異なるデータに対して処理を行うように自己スケジュールします。これにより、プログラム内の直列タスクと並列タスク(および複製タスク)の実行において、プロセス自身が協力して処理を行うように自己割り当てされます。
プロセスという概念は、プロセッサ上で複数のプロセスを実行できるという意味で、プロセッサという用語を一般化しました(たとえば、より高い効率と負荷分散のために、より高いレベルの並列性を活用するため)。 (IBM) SPMD モデルは、当時コミュニティの他の全員が追求していたフォークアンドジョインとは異なる、より効率的なアプローチとして Darema によって提案されました。また、単なる「データ並列」計算モデルよりも一般的で、フォークアンドジョイン (サブカテゴリの実装として) を包含することができます。 (IBM) SPMD の元のコンテキストは、分散メモリと (論理的に) 共有メモリの両方を備えた汎用コンピューティングをサポートする RP3 コンピュータ (512 プロセッサ IBM Research Parallel Processor Prototype) でした。[ 23 ] (IBM) SPMD モデルは、Darema と IBM の同僚によって、最初のプロトタイプ プログラミング環境の 1 つです。[ 6 ] [ 5 ] [ 4 ] [ 23 ] [ 24 ] [ 25 ] (IBM) SPMD の有効性は幅広いアプリケーションで実証されており、[ 23 ] [ 4 ]並列プログラミングの最初のベンダー製品である IBM FORTRAN に 1988 年に実装され、[ 26 ] MPI (1991 年以降)、OpenMP (1997 年以降)、および (IBM) SPMD 計算モデルを採用して引用しているその他の環境にも実装されています。
1980年代後半には、独自のメッセージパッシングライブラリを備えた分散コンピュータが数多く存在した。最初のSPMD標準はPVMであった。現在の事実上の標準はMPIである。
Crayの並列処理ディレクティブは、 OpenMPの直接の前身であった。
生成できない「非SPMD」ターゲット向け。これは、CPUやDSPなどのほぼすべての非GPUデバイスを網羅しています。