2009-08-08 18 views
7

Tôi đang viết một chương trình trong C cần thực hiện một số phép tính toán nhanh. Tôi đang sử dụng hướng dẫn lắp ráp SSE nội tuyến để có được một số hành động SIMD (sử dụng số điểm nổi chính xác gấp đôi được đóng gói). Tôi đang biên dịch bằng GCC trên Linux.Nhận GCC để duy trì thanh ghi SSE trong suốt một hàm sử dụng nội tuyến asm

Tôi đang trong tình huống cần phải lặp qua một số dữ liệu và tôi sử dụng yếu tố không đổi trong các phép tính của mình. Tôi muốn giữ yếu tố đó được giấu trong một thanh ghi an toàn trong vòng lặp, vì vậy tôi không phải nạp lại nó mỗi lần.

Để làm rõ với một số mã:

struct vect2 { 
    fltpt x; 
    fltpt y; 
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */ 
typedef struct vect2 vect2_t; 


void function() 
{ 
    /* get a specific value set up in xmm1, and keep it there for the 
    * rest of the loop. */ 
    for(int i = 0, i<N; i++){ 
     asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
     ); 
    } 
} 

Tôi đã cố gắng làm điều gì đó với "đăng ký" từ khóa. Nhưng nếu tôi không nhầm, có vẻ như tôi chỉ có thể giữ một con trỏ cho cấu trúc đó (trong sổ đăng ký chung). Điều này sẽ cần phải được trì hoãn mỗi lần lặp lại, lãng phí thời gian quý báu.

register vect2_t hVect asm("xmm1") = {h, h}; 
/* Gives error: data type of 'hVect' isn't suitable for a register */ 

register vect2_t *hVect2 asm("rax"); 
*hVect2 = (vect2_t){h,h}; 
/* Seems to work, but not what I'm looking for */ 

Tôi không thích giả định rằng GCC sẽ không thay đổi sổ đăng ký xmm1, nó quá nhiều của một "ác quỷ bay ra khỏi mũi" loại điều :-). Vì vậy, tôi hy vọng có một cách thích hợp để làm điều này.

Trả lời

8

Tôi nghĩ giải pháp ở đây là làm cho gcc biết rằng loại vec2_t của bạn thực sự là một vectơ; sau đó bạn chỉ có thể tính toán giá trị loop-bất biến và đối xử với nó như là một biến bình thường (trừ các trình biên dịch biết nó là một loại vector):

typedef double vec2_t __attribute__ ((vector_size (16))); 

void function() 
{ 
    /* get a specific value set up, e.g. */ 
    vec2_t invariant; 
    asm("some calculations, soring result in invariant." 
     : "=x" (invariant)); 

    for(int i = 0; i<N; i++){ 
    asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
      : "x" (invariant) // and other SSE arguments 
     ); 
    } 
} 

tôi đã biên dịch này lên với một phép tính đơn giản bên trong vòng lặp, và với ít nhất là mức tối ưu hóa 1, giá trị của invariant được giữ trong sổ đăng ký XMM trong vòng lặp.

(Tất cả điều này giả định bạn không cần bất biến vòng lặp của bạn trong sổ đăng ký XMM rõ ràng; và bạn có thể sử dụng phân bổ đăng ký bình thường của GCC).

3

Tôi nghĩ tốt nhất nên để bài tập đăng ký cho trình biên dịch. Nó có thể có thể theo dõi tốt hơn của nó hơn bạn. GCC sẽ đã sử dụng các phần mở rộng SSE nhưng nếu bạn chắc chắn rằng bạn biết rõ hơn, hãy sử dụng các hàm GCC __builtin. Thành thật mà nói, tôi nghi ngờ một chút rằng bạn sẽ làm cho nó nhanh hơn theo cách đó.

Chúc bạn may mắn!

Các trang web này có thể thú vị khi xem xét.

GCC X86 Built-in functions

Working with SIMD with GCC

3

Tôi đang sử dụng để làm việc với lắp ráp và C và những gì tôi sẽ làm gì ở đây là tôi sẽ viết toàn bộ chức năng trong lắp ráp. Nếu bạn có hệ thống tạo linh hoạt, tôi khuyên bạn nên lắp ráp riêng chức năng ASM và liên kết nó với ứng dụng của bạn. Vấn đề duy nhất với điều này là hàm không thể được biên dịch bởi trình biên dịch.

chức năng void (void); // C

chức năng "C" bên ngoài (void); // C++

Các vấn đề liên quan