Làm thế nào bạn có thể chèn NaN vào một thanh ghi xmm?


9

Đối với chức năng tôi đang viết, tôi muốn trả về Nan nếu đầu vào không có ý nghĩa.

Làm cách nào tôi có thể chèn NaN vào thanh ghi xmm một cách dễ nhất?


1
Làm thế nào để bạn xác định "đầu vào không có ý nghĩa"? Nếu đây là kết quả của một phép so sánh, bạn có thể chỉ cần bitwise - hoặc kết quả "bình thường" của bạn với mặt nạ kết quả của phép so sánh.
chtz

Câu trả lời:


13

Tất cả mọi người là một NaN yên tĩnh (không tín hiệu, hay bình thường), đó là những gì bạn muốn. Cách dễ nhất để tạo một cái là với SSE2 pcmpeqd xmm0,xmm0để đặt mọi bit trong thanh ghi 1, tức là số nguyên bổ sung của 2 -1. ( Đặt tất cả các bit trong thanh ghi CPU thành 1 hiệu quả / Chuỗi lệnh tốt nhất để tạo các hằng số vectơ là gì? )

Đó thực sự là một -NaN- bit dấu được đặt. Xem xét dịch chuyển số nguyên phải ( psrld xmm0,1) hoặc chia cho 0/0 ( xorps xmm0,xmm0/ divpd xmm0,xmm0) nếu điều đó là không mong muốn.


Các hàm toán học muốn trả về NaN thường cũng muốn đảm bảo bit ngoại lệ dính không hợp lệ của FP được đặt trong MXCSR (hoặc thực sự đưa ra một ngoại lệ nếu người gọi của bạn vạch mặt ngoại lệ đó). Để làm điều đó , bạn có thể nhân hoặc thêm NaN với chính nó. ví dụ

    ...
.error_return_path:
    pcmpeqd   xmm0, xmm0
    mulsd     xmm0, xmm0       ; Cause an FP-invalid operation.
    ret

Hoặc mulsscho độ chính xác đơn float. mulpd/ mulpscũng sẽ thích hợp.

Mẫu bit để nhân hoặc thêm NaN với NaN chắc chắn vẫn là NaN và vẫn phải là cùng một trọng tải, vì vậy vẫn là tất cả.

Có giá trị trả về là kết quả của mulsdhoặc addsd(hoặc divsd) cũng có lợi thế là nếu người gọi sử dụng thanh ghi đó lặp đi lặp lại trong một vòng lặp, thì nó sẽ không có độ trễ bỏ qua miền. (Trên gia đình Sandybridge, điều này tồn tại mãi mãi. Ví dụ: mọi người addsd xmm1, xmm0sẽ có thêm một chu kỳ trễ từ đầu vào xmm1 đến đầu ra xmm1 nếu xmm0 xuất phát pcmpeqd, ngay cả khi điều đó đã lâu và uop SIMD số nguyên đã ngừng hoạt động.)


Bạn thậm chí có thể làm điều đó một cách không phân nhánh nếu bạn sử dụng cmpsdhoặc cmppd: bạn có thể orpstạo mặt nạ 0 / -1 đó để biến nó thành NaN hoặc không thay đổi. Nếu một số tính toán khác sẽ (hoặc sẽ có) đặt cờ không hợp lệ hoặc nếu bạn không quan tâm đến điều đó, bạn đã hoàn tất.

Cảnh giác với việc kéo dài đường dẫn quan trọng có thêm cmp / hoặc; nếu bạn cho rằng nó rất hiếm, bạn vẫn có thể so sánh và phân nhánh, ví dụ với movmskpd/ test eax,eax/ jnztrên kết quả cmppd để xem liệu một trong hai bit đã được đặt => một trong các phần tử SIMD đã thất bại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.