Cách nhân bốn số nguyên 32 bit bằng 4 số nguyên khác? Tôi không tìm thấy bất kỳ hướng dẫn nào có thể thực hiện được.Nhân SSE 4 số nguyên 32 bit
Trả lời
Nếu bạn cần ký 32x32 bit số nguyên nhân sau đó ví dụ sau tại software.intel.com vẻ như nó nên làm những gì bạn muốn:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
__m128i tmp1 = _mm_mul_epu32(a,b); /* mul 2,0*/
__m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(a,4), _mm_srli_si128(b,4)); /* mul 3,1 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
}
Bạn có thể muốn có hai xây dựng - một cho CPU cũ và một đối với các CPU gần đây, trong trường hợp đó, bạn có thể thực hiện các thao tác sau:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
#ifdef __SSE4_1__ // modern CPU - use SSE 4.1
return _mm_mullo_epi32(a, b);
#else // old CPU - use SSE 2
__m128i tmp1 = _mm_mul_epu32(a,b); /* mul 2,0*/
__m128i tmp2 = _mm_mul_epu32(_mm_srli_si128(a,4), _mm_srli_si128(b,4)); /* mul 3,1 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
#endif
}
PMULLD, từ SSE 4.1, thực hiện điều đó.
Mô tả hơi gây nhầm lẫn, nó nói về phép nhân đã ký, nhưng vì nó chỉ lưu trữ 32 bit thấp hơn, nên đó thực sự là hướng dẫn không biết chữ mà bạn có thể sử dụng cho cả hai, giống như IMUL
.
Cảm ơn. Nhưng có cách nào để chỉ sử dụng các chỉ dẫn SSE 2 không? – Yury
'_mm_mullo_epi32' nếu bạn muốn sử dụng nội tại hơn so với tập hợp thô –
@Leviathan Có, nhưng bạn cần một số hướng dẫn. Tùy thuộc vào kiến trúc, bốn 'imul' có thể nhanh hơn và đơn giản hơn – hirschhornsalz
Câu trả lời hay. Hài hước bạn đã thực hiện chính xác cùng một lỗi đánh máy tôi đã có một lần trong mã của tôi: Nó phải là _____SSE4_1_____ (không có gạch dưới giữa E và 4). Gây phiền nhiễu, bởi vì bạn không nhận thấy nó dễ dàng - chương trình chạy hoàn hảo miễn là đường dẫn mã thay thế là ok – hirschhornsalz
@drhirsch: cảm ơn bạn đã sửa chữa - trong mã thực tôi có xu hướng sử dụng '__MNI__',' __SNI__', v.v. chủ yếu vì lý do lịch sử, nhưng nó cũng ít bị lỗi đơn giản hơn như trên. –
Tuyệt vời, cảm ơn! Bây giờ, nếu chỉ có một mẹo tương tự để thay thế '_mm_insert_epi32' trên CPU chỉ với SSE2 ... –