Làm thế nào để cải thiện hiệu năng của các chương trình gọi các hàm toán học

Lợi dụng véc tơ hóa tự động của trình biên dịch XL C/C++ hoặc XL Fortran của IBM

Bài viết này giới thiệu các thư viện toán học hiệu năng cao MASS của IBM và giải thích cách hưởng lợi từ chúng — mà không cần thay đổi chương trình mã nguồn — nhờ sử dụng khả năng véc tơ hóa tự động của các trình biên dịch XL C/C++ và XL Fortran của IBM®. Sau khi giới thiệu khái niệm về vector hóa tự động và các tùy chọn trình biên dịch có liên quan, một trường hợp nghiên cứu của một chương trình biến đổi Phu ri ê rời rạc được đưa ra làm một ví dụ thực tế về véc tơ hóa tự động.

Robert F. Enenkel, Nhà phát triển phần mềm, IBM

Robert Enenkel làm việc trong nhóm Các trình biên dịch tối ưu (Optimizing Compiler Group) tại Phòng thí nghiệm Toronto của IBM; trước đây ông là nghiên cứu viên tại Trung tâm Nghiên cứu cao cấp của IBM (CAS). Enenkel nhận được bằng Cử nhân khoa học, Thạc sĩ khoa học và bằng tiến sĩ triết học của Đại học Toronto, với luận án về lĩnh vực các phương pháp số song song cho các phương trình vi phân. Ông hiện đang nghiên cứu và phát triển về điện toán số vì nó liên quan đến các trình biên dịch và các hệ điều hành, bao gồm cả số học dấu phẩy động, các thư viện hàm toán học và điều chỉnh hiệu năng của các thuật toán. Tiến sĩ Enenkel đã nhận được nhiều giải thưởng về sáng chế của IBM và giải thưởng công nhận tác giả. Có thể tìm thêm nhiều thông tin tại trang web của ông tại https://www-927.ibm.com/ibm/cas/toronto/people/members/renekel.shtml.



Daniel M. Zabawa, Nhà phát triển phần mềm, IBM

Daniel Zabawa làm việc trong nhóm Các trình biên dịch tối ưu (Optimizing Compiler Group) tại Phòng thí nghiệm Toronto của IBM. Ông đã nhận bằng Cử nhân khoa học và Thạc sĩ khoa học về Khoa học Máy tính của Đại học Toronto. Zabawa hiện đang thực hiện nghiên cứu và phát triển về tối ưu hóa và lập biểu vòng lặp, các thuật toán dấu phẩy động cho các kiến trúc chỉ số trên và thực hiện điều chỉnh các hàm toán học dấu phẩy động.



28 05 2011

Các thư viện hiệu năng cao MASS

MASS là viết tắt của Hệ thống con tăng tốc toán học (Mathematical Acceleration Subsystem). Nó bao gồm các thư viện về các hàm toán học đặc biệt được điều chỉnh cho hiệu năng tối ưu trên các nền tảng điện toán khác nhau của IBM. Ban đầu MASS đã được IBM khởi chạy vào năm 1995. Và từ đó đã liên tục được cải tiến và mở rộng.

Hiện đang có các phiên bản của MASS cho tất cả các bộ vi xử lý POWER™ của IBM®, đang chạy các hệ thống điều hành AIX® hoặc Linux®. Ngoài ra còn có các phiên bản dành cho các siêu máy tính System BlueGene®/Lvà the IBM System BlueGene®/P của IBM cũng như giải pháp Cell Broadband Engine™ (Cell/B.E.™) của IBM. Các thư viện chứa các triển khai thực hiện có tăng tốc của các hàm cơ sở như các hàm lượng giác và hyperbolic và hàm nghịch đảo, hàm lũy thừa, hàm logarit, hàm mũ, hàm lỗi và các hàm khác của chúng. Danh sách đầy đủ về các hàm bao gồm có sẵn trên trang Hệ thống con tăng tốc toán học của IBM.

Có cả thư viện vô hướng và véc tơ và cũng có các thư viện đa dữ liệu (SIMD) lệnh đơn cho Cell/B.E. và POWER7. Lưu ý rằng việc xử lý chính xác và xử lý ngoại lệ có thể không giống nhau trong các hàm MASS và các hàm thư viện hệ thống. Các thư viện được đóng gói bằng các trình biên dịch XL C/C++ và XL Fortran của IBM và cũng có sẵn trên trang web MASS, cho những người dùng của các trình biên dịch khác (chẳng hạn như gcc) với phần cứng đã định.

Các thư viện có thể gọi được từ các chương trình nguồn C, C++ hoặc Fortran. Các trình biên dịch XL C/C++ và XL Fortran của IBM có khả năng nhận ra những cơ hội sử dụng MASS để tăng tốc chương trình nguồn và gọi nó tự động mà không cần các thay đổi chương trình nguồn. Bài viết này cho bạn thấy làm thế nào để triển khai thực hiện một kỹ thuật có thể giúp tổ chức của bạn tận dụng khả năng mạnh mẽ này.

Các chương trình có thể được lợi gì?

Bất kỳ chương trình C, C++ hoặc Fortran đều có chứa các cuộc gọi đến các hàm thư viện toán học (như hàm mũ, hàm logarit, hàm sin, hàm cos, v.v) trong một vòng lặp có thể được lợi nhiều từ các kỹ thuật được mô tả trong bài viết này.


Véc tơ hóa tự động là gì?

Véc tơ hóa tự động là một quá trình mà theo đó các trình biên dịch XL C/C++ hay Fortran của IBM nhận ra cơ hội để cải thiện hiệu năng của chương trình đang được biên dịch bằng cách thay thế một cuộc gọi đến một hàm (bên trong của C/C++ libm hoặc Fortran) thư viện chuẩn trong một vòng lặp bằng một cuộc gọi đến hàm véc tơ MASS tương ứng. Do các hàm véc tơ MASS nhanh hơn nhiều (với hệ số tăng đến khoảng 30 lần) so với một cuộc gọi lặp lại tới một hàm thư viện chuẩn, nên việc cải thiện hiệu năng kết quả có thể đáng kể.

Một ví dụ đơn giản là một vòng lặp để tính toán một hàm cụ thể có nhiều đối số, ví dụ như chương trình Fortran sau đây.

subroutine sub (y, x, n)
    real*8 y(*), x(*)
    integer n, i
    intrinsic exp
    do i=1,n
        y(i) = exp(x(i))  ! standard intrinsic
    end do
end subroutine

Với các tùy chọn trình biên dịch thích hợp, trình biên dịch sẽ nhận ra cơ hội để tăng tốc chương trình bằng cách thay thế cuộc gọi lặp lại đến hàm exp() bằng một cuộc gọi duy nhất đến hàm véc tơ MASS tương ứng vexp(), kết quả là một chương trình chạy như thể ngay từ đầu nó đã được viết ra như sau:

include 'massv.include'
subroutine sub (y, x, n)
    real*8 y(*), x(*)
    integer n
    call vexp (y, x, n)  ! MASS vector function
end subroutine

Đây chỉ là một ví dụ đơn giản, thể hiện ý tưởng cơ bản đằng sau việc véc tơ hóa tự động. Các trình biên dịch XL thực sự có thể nhận ra nhiều cơ hội phức tạp hơn và cũng sẽ cố gắng sắp xếp lại các lệnh trong chương trình nguồn khi cần thiết để tạo các cơ hội véc tơ hóa tự động.

Một ví dụ thực tế và phức tạp hơn được xem xét trong phần trường hợp nghiên cứu của bài viết này.


Các tùy chọn trình biên dịch với việc véc tơ hóa tự động

Bạn có thể biên dịch các chương trình với bất kỳ một trong các bộ các tùy chọn sau:

  1. -qhot -qnostrict (với Fortran)
  2. -qhot -qnostrict -qignerrno (với C/C++)
  3. -qhot -O3
  4. -O4
  5. -O5

Khi bạn biên dịch một chương trình bằng cách sử dụng một trong các bộ tùy chọn này, trình biên dịch tự động cố thử véc tơ hóa cuộc gọi đến các hàm toán của hệ thống bằng cách gọi các hàm véc tơ MASS tương đương (trừ các cuộc gọi đến các hàm sau, là các hàm ngoại lệ: vdint vatan2, vsatan2, vdnint, , vcosisin, vscosisin, vlog21p vqdrt, vsqdrt, vrqdrt, vsrqdrt, vpopcnt4, vpopcnt8, vexp2, vexp2m1, vsexp2, vsexp2m1, vlog2,, vslog2 và vslog21p). Nếu trình biên dịch không thể véc tơ hóa chương trình như vậy, nó sẽ thực hiện gọi tự động các hàm vô hướng MASS tương đương. Để véc tơ hóa hoặc vô hướng hóa tự động, trình biên dịch sử dụng các phiên bản của các hàm MASS có trong thư viện libxlopt.a của trình biên dịch. Bạn không cần phải thêm bất kỳ cuộc gọi đặc biệt nào nữa đến các hàm MASS trong mã của bạn hoặc liên kết rõ ràng đến thư viện xlopt.

Ngoài bất kỳ các bộ tùy chọn có trước, khi tùy chọn –qipa có hiệu lực, nếu trình biên dịch không thể véc tơ hóa được, nó sẽ cố gắng nội tuyến các hàm vô hướng MASS trước khi quyết định gọi chúng.

Nếu bạn muốn vô hiệu hóa việc véc tơ hóa tự động, bạn có thể thêm tùy chọn -qhot=novector.


Trường hợp nghiên cứu

Sau đây là một trường hợp nghiên cứu về một ứng dụng thực tế — một phép biến đổi Phu ri ê rời rạc (DFT) — cho thấy các cải tiến hiệu năng nhận được khi biên dịch với các tùy chọn của trình biên dịch khác nhau. Ứng dụng đủ đơn giản để được minh họa rõ ràng, nhưng cũng đủ phức tạp để cung cấp các cơ hội tối ưu hóa không tầm thường.

Việc tính giờ cho cả hai chương trình đã được thực hiện bằng chương trình của trình điều khiển được cho trong Phụ lục 3, trên một máy tính POWER6 chạy ở 4,704 GHz.

Phụ lục 1 cho thấy chương trình nguồn DFT Fortran. Nó chứa một vòng lặp lồng nhau để gọi hàm exp(), cos() và sin(), theo sau là một vòng lặp để gọi hàm sin () và sqrt (). Chương trình được biên dịch theo tùy chọn -O3 (không thực hiện véc tơ hóa tự động) và theo tùy chọn -O4 (thực hiện véc tơ hóa tự động). Kết quả được chỉ ra trong Hình 1.

Lưu ý rằng lợi ích của việc véc tơ hóa tự động tăng lên khi kích cỡ bài toán được tăng lên, đạt tới một hệ số cải thiện tăng gấp 8,94 lần với một kích cỡ bài toán là 2000.

Hình 1: So sánh hiệu năng của DFT Fortran với các tùy chọn biên dịch -O3 và -O4, với các kích cỡ bài toán khác nhau.
Biểu đồ biểu thi các giây cho mỗi phần tử so với kích cỡ bài toán.

Phụ lục 2 cho thấy một phiên bản C của chương trình DFT Fortran trong Phụ lục 1 (Nó chứa một thường trình consume() giả để cho việc phân tích giữa-thủ tục [IPA] của trình biên dịch không thể nhận thấy rằng kết quả tính toán này thực tế không được sử dụng trong ví dụ minh họa này và do đó sẽ tối ưu hóa ngay toàn bộ chương trình).

Chương trình được biên dịch theo tùy chọn -O3 (không thực hiện véc tơ hóa tự động), theo tùy chọn -O4 (thực hiện véc tơ hóa tự động) và -O5 (thực hiện véc tơ hóa tự động cũng như IPA). Kết quả được chỉ ra trong Hình 2.

Như được minh họa trong ví dụ Fortran, lợi ích của việc véc tơ hóa tự động tăng lên khi kích thước bài toán được tăng lên, đạt tới hệ số gấp 6,00 lần với n = 2000. Ngoài ra, việc kích hoạt IPA tại -O5 cung cấp tăng tốc thêm 1,22 lần do nó có thể xác định rằng các đầu vào và các đầu ra không phải là bí danh (có nghĩa là, chúng không chồng lấp lên nhau trong bộ nhớ), cho phép nó véc tơ hóa cuộc gọi đến atan2 trong phép biến đổi sang hệ tọa độ cực. Sự tăng tốc của -O5 hơn -O3 là 7,33 lần với n=2000.

Hình 2: So sánh hiệu năng DFT C với các tùy chọn biên dịch -O3, -O4 và -O5, với các kích cỡ bài toán khác nhau.
Biểu đồ biểu thi các giây cho mỗi phần tử so với kích cỡ bài toán.

Kết luận

Bài viết này đã cung cấp cho bạn một mô tả về các thư viện MASS của IBM và các khả năng véc tơ hóa tự động của các trình biên dịch XL C/C++ và XL Fortran của IBM. Ngoài ra, bài viết đã giải thích cách sử dụng các tùy chọn trình biên dịch khác nhau trên một chương trình ví dụ (phép biến đổi Phu ri ê rời rạc), chỉ cho bạn biết cách có thể đạt được các tăng tốc lên tới 8,94 lần so với các tốc độ trước đây nhờ sử dụng các trình biên dịch thông qua cuộc gọi tự động của MASS bằng véc tơ hóa tự động.

Cuộc trình diễn này là nhằm khuyến khích những người dùng với các chương trình để gọi các hàm toán học để thử nghiệm với các tùy chọn trình biên dịch có sẵn và hưởng lợi từ sự tăng tốc là kết quả của việc véc tơ hóa tự động trình biên dịch XL C/C++ hoặc XL Fortran của IBM .


Phụ lục 1 – Chương trình nguồn Biến đổi Phu ri ê rời rạc (DFT) của Fortran

  subroutine dft (x, a, phi , n)
    real*8 x(n), a(n), phi(n)
    integer n

    ! Compute discrete Fourier transform of real inputs         
    ! x(i) and convert to polar form.

    real*8, parameter :: pi=3.1415926535897932384d0
    real*8 y_re(n), y_im(n), t, term_re, term_im
    intrinsic exp, cos, sin, sqrt, atan

    y_re(1:n) = 0.d0
    y_im(1:n) = 0.d0
    do k=1,n
      ! compute y(k), k-th DFT output
      do i=1,n
        ! compute i-th term of y(k):
        ! x(k)*exp(-2*pi*I*(k-1)*(i-1)/n)
        ! compute real and imaginary parts of i-th term
        ! using exp(I*t)=exp(t)*(cos(t)+I*sin(t))

        t = -2.d0*pi*(k-1)*(i-1)/n
        term_re = x(i) * cos(t) * exp(t)
        term_im = x(i) * sin(t) * exp(t)

        ! add term to sum
        y_re(k) = y_re(k) + term_re
        y_im(k) = y_im(k) + term_im
      end do
    end do

    ! transform y to polar coordinates
    do k=1,n
      ! compute amplitude of y(k)
      a(k) = sqrt (y_re(k)**2 + y_im(k)**2)
      ! compute phase of y(k)
      phi(k) = atan (y_im(k) / y_re(k))
    end do

  end subroutine

  ! initialize input data
  subroutine init (a, n)
    real*8 a(n)
    integer n
    intrinsic sin,sqrt
    
    do j=1,n
      a(j)=sin(1.d0/sqrt(real(j,8)))
    end do
  end subroutine

Phụ lục 2 – Chương trình nguồn Biến đổi Phu ri ê rời rạc (DFT) của C

#include <math.h>
#define PI 3.1415926535897932384
void dft(double x[],double a[],double phi[],int *m)
{
  double y_re[NMAX], y_im[NMAX], t, s, term_re, term_im;
  int i,j,k,n=*m;
  for(i=0;i<n;++i) {
    y_re[i]=y_im[i]=0;
  }
  for(k=0;k<n;++k) 
  {
    // compute y(k), k-th DFT output
    for(i=0;i<n;++i)
    {
      // compute i-th term of y(k):
      // x(k)*exp(-2*pi*I*(k-1)*(i-1)/n)
      // compute real and imaginary parts of i-th term
      // using exp(I*t)=exp(t)*(cos(t)+I*sin(t))

      t=-2.*PI*k*i/(double)n;
      term_re=x[i]*exp(t)*cos(t);
      term_im=x[i]*exp(t)*sin(t);

      // add term to sum
      y_re[k]+=term_re;
      y_im[k]+=term_im;
    }
  }

  // transform y to polar coordinates
  for(k=0;k<n;++k)
  {
    // compute amplitude of y(k)
    a[k]=sqrt(y_re[k]*y_re[k]+y_im[k]*y_im[k]);
    // compute phase of y(k)
    phi[k]=atan2(y_im[k],y_re[k]);
  }
}

// initialize input data
void init(double a[],int *m)
{
  int j,n=*m;
  for(j=0;j<n;++j) 
  {
    a[j]=sin(1./sqrt((double)j+1.0));
  }
}

// Dummy function to use result, preventing compiler from
// optimizing away the computation.
void consume(double a[],double b[],double c[])
{
}

Phụ lục 3 – Chương trình trình điều khiển

Đây là chương trình của trình điều khiển Fortran đã được sử dụng để tính giờ các mã DFT.

  program main
    interface
      subroutine dft(x,a,phi,n)
      real*8 x(n),a(n),phi(n)
      integer n
      end subroutine
      subroutine init(a,n)
      real*8 a(n)
      integer n
      end subroutine
      subroutine consume(a,b,c)
      real*8 a(*),b(*),c(*)
      end subroutine
    end interface

    ! Parameters:
    !   nmax is the problem size.
    !   nrep is the number of repetitions of the
    !        problem. This should be chosen so that
    !        the elapsed time is long enough to give
    !        sufficient timing resolution.
    !   cyc is the clock frequency in Hz for the
    !       processor that the program is to be run on.
    !       (Can be found from AIX command pmcycles.)
    
    integer, parameter :: nmax=1000
    integer, parameter :: nrep=100
    real*8, parameter :: cyc=4704000000.d0

    real*8 x(nmax), a(nmax), phi(nmax)
    real*8 tx, ty, accum, del(4)
    intrinsic sin, sqrt
    real*8 rtc

    del(4)=0.d0
    acc = 0.d0
    do k=1,nrep
      tx=rtc()
      call init(x,nmax)
      call dft(x,a,phi,nmax)
      ty=rtc()
      call consume(x,a,phi)
      do j=1,nmax
        acc = acc + a(j) + phi(j)
      end do
      del(4) = del(4) + (ty-tx)
    end do
    del(1) = del(4)/real(nmax,8)
    del(2) = del(1)/real(nrep,8)
    del(3) = cyc*del(2)
    print *,'acc=',acc/real(nrep,8),' n=',nmax,
 &    ' r=',nrep, ' a=',del(1),' b=',del(2),
 &    ' c=',del(3),' w=',del(4)
  end program

Không chấp nhận khiếu nại

Hiệu năng chính xác đạt được có thể khác nhau tùy thuộc vào loại bộ vi xử lý được sử dụng và cấu hình của nó, cũng như vào phiên bản của trình biên dịch được sử dụng. Do đó, bạn có thể trải nghiệm hiệu năng khác với hiệu năng đã đạt được trong các thử nghiệm được mô tả ở đây.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Rational
ArticleID=661146
ArticleTitle=Làm thế nào để cải thiện hiệu năng của các chương trình gọi các hàm toán học
publish-date=05282011