2013-08-13 30 views
7

Tôi đang viết một chương trình thử nghiệm để làm quen với các phần mở rộng ngôn ngữ của Clang cho các vector kiểu OpenCL. Tôi có thể nhận được mã để làm việc nhưng tôi đang gặp vấn đề nhận được một khía cạnh của nó xuống. Tôi không thể tìm ra cách để có được clang chỉ cần tải trong một vector từ một mảng vô hướng độc đáo.Cách tốt hơn để tải vectơ từ bộ nhớ. (clang)

Tại thời điểm này tôi phải làm một cái gì đó như:

byte16 va = (byte16){ argv[1][start], argv[1][start + 1], argv[1][start + 2], 
         argv[1][start + 3], argv[1][start + 4], argv[1][start + 5], 
         argv[1][start + 6], argv[1][start + 7], argv[1][start + 8], 
         argv[1][start + 9], argv[1][start + 10], argv[1][start + 11], 
         argv[1][start + 12], argv[1][start + 13], argv[1][start + 14], 
         argv[1][start + 15]}; 

tôi sẽ lý tưởng như một cái gì đó như thế này:

byte16 va = *(byte16 *)(&(argv[1][start])); 

Mà tôi có thể dễ dàng làm gì sử dụng intrinsics thích hợp cho ARM hay x86. Nhưng mã đó làm cho chương trình bị lỗi mặc dù nó biên dịch.

+0

Không phải 'memcpy (& va, & argv [1] [bắt đầu], sizeof (va)) 'có hoạt động không? – jxh

Trả lời

5

Một trong những lý do sự cố có thể xảy ra trên x86 là do sự cố liên kết. Tôi không có tiếng kêu trên hệ thống của mình để tái tạo vấn đề, nhưng tôi có thể chứng minh nó ở ví dụ về GCC.

Nếu bạn làm điều gì đó như:

/* Define a vector type of 16 characters. */ 
typedef char __attribute__ ((vector_size (16))) byte16; 

/* Global pointer. */ 
char * foo; 

byte16 test() 
{ 
    return *(byte16 *)&foo[1]; 
} 

Bây giờ nếu bạn biên dịch nó trên một x86 vector có khả năng với:

$ gcc -O3 -march=native -mtune=native a.c 

Bạn sẽ có được lắp ráp sau đây để kiểm tra:

test: 
    movq foo(%rip), %rax 
    vmovdqa 1(%rax), %xmm0 
    ret 

Xin lưu ý rằng di chuyển được căn chỉnh, tất nhiên là sai. Bây giờ, nếu bạn nhập nội dung này vào chính, và bạn sẽ có một cái gì đó như:

int main() 
{ 
    foo = __builtin_malloc (22); 
    byte16 x = *(byte16 *)&foo[1]; 
    return x[0]; 
} 

Bạn sẽ ổn, và bạn sẽ nhận được hướng dẫn chưa được ký. Đây là một loại lỗi, mà không có một sửa chữa rất tốt trong trình biên dịch, vì nó sẽ yêu cầu tối ưu hóa interprocedural với việc bổ sung các cấu trúc dữ liệu mới, v.v.

Nguồn gốc của vấn đề là trình biên dịch giả định rằng các loại vectơ được căn chỉnh, vì vậy khi bạn dereference một mảng của các loại vector liên kết, bạn có thể sử dụng một di chuyển liên kết. Giải pháp cho vấn đề trong GCC có thể xác định loại vectơ không được ký hiệu như:

typedef char __attribute__ ((vector_size (16),aligned (1))) unaligned_byte16; 

Và sử dụng nó cho bộ nhớ chưa được ký kết.

Tôi không chắc chắn rằng bạn đang nhấn chính xác vấn đề này trong thiết lập của bạn, nhưng đây là một cái gì đó mà tôi sẽ khuyên bạn nên kiểm tra bằng cách kiểm tra đầu ra lắp ráp từ trình biên dịch của bạn.

+0

Vâng, trong trường hợp đó tôi không thấy bất kỳ lý do tại sao nó sẽ thất bại ... Bạn có thể thử làm một cái gì đó như thế này: 'struct b16 { char x [16]; }; struct b16 x = * (struct b16 *) & argv [1] [0]; ' –

+1

Tôi gặp vấn đề tương tự khi sử dụng Clang và kiểm tra lắp ráp (lắp ráp ARM, tìm kiếm" ': 64'" hoặc "': 128' "trong trường địa chỉ) tôi có thể thấy rằng nó đang sử dụng các phiên bản liên kết của tải và hướng dẫn lưu trữ. Giải pháp này làm việc cho tôi. – sh1

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