向量處理器

向量處理器,又稱數組處理器,是一種實現了直接操作一維數組(向量)指令集的中央處理器(CPU)。與之相比,純量處理器一次只能處理一個數據。向量處理器可以在特定工作環境中極大地提升性能,尤其是在數值模擬或者相似領域。向量處理器最早出現於1970年代早期,並在1970年代到1990年代期間主導了超級計算機的設計方向,尤其是多個克雷(Cray)平台。由於90年代末純量處理器設計性能提升,而價格快速下降,基於向量處理器的超級計算機逐漸讓出了主導地位。

並行向量處理機
處理器類型
上級分類處理器 編輯
用途高性能計算、​超級計算機 編輯
相對概念純量處理器 編輯
克雷YMP向量電腦的處理器板

現在,絕大多數商業化的CPU實現都能夠提供某種形式的向量處理的指令,用來處理多個(向量化的)數據集,也就是所謂的SIMD(單一指令、多重數據)。常見的例子有 VIS, MMX, SSE, AltiVecAVX。向量處理技術也能在遊戲主機硬件圖形加速硬件上看到。在2000年,IBM東芝索尼合作開發了Cell處理器,集成了一個純量處理器和八個向量處理器,應用在索尼的PlayStation 3遊戲機和其他一些產品中。

其他CPU設計還可能包括多重指令處理多重(向量化的)數據集的技術——也就是所謂的MIMD(多重指令、多重數據)——並實現了VLIW。此類設計通常用於特定應用場合,而不是面向通用計算機的市場化產品。在富士通的 FR-V VLIW/vector 處理器中,組合使用了兩種技術。

基本特點

平行向量處理機最大的特點是系統中的CPU是專門定製的向量處理器(VP)。系統還提供共享存儲器以及與VP相連的高速交叉開關。

來自現實世界的例子: x86 架構中的向量指令應用

// 改自英文維基 Vector_processor
//SSE simd function for vectorized multiplication of 2 arrays with single-precision floatingpoint numbers
//1st param pointer on source/destination array, 2nd param 2. source array, 3rd param number of floats per array
void mul_asm(float* out, float* in, unsigned int leng){
      unsigned int count, rest;

      //compute if array is big enough for vector operation
      rest  = (leng*4)%16;
      count = (leng*4)-rest;

     // vectorized part; 4 floats per loop iteration
      if (count>0){
      __asm __volatile__  (".intel_syntax noprefix\n\t"
      "loop:                 \n\t"
      "sub ecx,16            \n\t" // decrease address pointer by 4 floats
      "movups xmm0,[ebx+ecx] \n\t" // loads 4 floats in first register (xmm0)
      "movups xmm1,[eax+ecx] \n\t" // loads 4 floats in second register (xmm1)
      "mulps xmm0,xmm1       \n\t" // multiplies both vector registers
      "movups [eax+ecx],xmm0 \n\t" // write back the result to memory
      "jnz loop              \n\t"
      ".att_syntax prefix    \n\t"
        : : "a" (out), "b" (in), "c"(count), "d"(rest): "xmm0","xmm1");
      }

      // scalar part; 1 float per loop iteration
      if (rest!=0)
      {
       __asm __volatile__  (".intel_syntax noprefix\n\t"
      "add eax,ecx           \n\t"
      "add ebx,ecx           \n\t"

      "rest:                 \n\t"
      "sub edx,4             \n\t"
      "movss xmm0,[ebx+edx]  \n\t" // load 1 float in first register (xmm0)
      "movss xmm1,[eax+edx]  \n\t" // load 1 float in second register (xmm1)
      "mulss xmm0,xmm1       \n\t" // multiplies both scalar parts of registers
      "movss [eax+edx],xmm0  \n\t" // write back the result\n\t"
      "jnz rest              \n\t"
      ".att_syntax prefix    \n\t"
        : : "a" (out), "b" (in), "c"(count), "d"(rest): "xmm0","xmm1");
      }
      return;
}

參閱