Pertanyaan Apakah ada cara untuk mensimulasikan operasi bitwise integer untuk jenis _m256 pada AVX?


Saya memiliki ekspresi boolean yang berhasil saya implementasikan dalam SSE2. Sekarang saya ingin mencoba menerapkannya dalam AVX dengan memanfaatkan faktor tambahan 2 dalam peningkatan paralelisme (dari tipe 128 bit SIMD hingga 256). Namun, AVX tidak mendukung operasi integer (yang AVX2 lakukan, tetapi saya bekerja pada prosesor Sandy Bridge sehingga ini bukan pilihan saat ini). Namun, karena memang ada AVX intrinsik untuk operasi bitwise. Saya pikir saya bisa mencoba dengan hanya mengkonversi tipe integer saya ke tipe float dan melihat apakah itu berfungsi.

Tes pertama berhasil:

__m256 ones = _mm256_set_ps(1,1,1,1,1,1,1,1);
__m256 twos = _mm256_set_ps(2,2,2,2,2,2,2,2); 
__m256 result = _mm256_and_ps(ones, twos);

Saya melakukan semua hal yang seharusnya saya lakukan. Secara simultan AND'ing twos, saya mendapatkan hasil 2. Tetapi ketika mencoba 11 XOR 4, maka:

__m256 elevens = _mm256_set_ps(11,11,11,11,11,11,11,11); 
__m256 fours = _mm256_set_ps(4,4,4,4,4,4,4,4); 
__m256 result2 = _mm256_xor_ps(elevens, fours); 

Hasilnya adalah 6.46e-46 (yaitu hampir 0) dan tidak 15. Secara simultan, 11 atau 4 memberi saya nilai 22 dan bukan 15 seperti seharusnya. Saya tidak mengerti mengapa ini. Apakah ini bug atau beberapa konfigurasi yang saya lewatkan?

Saya benar-benar mengharapkan hipotesis saya bekerja dengan float seolah-olah mereka bilangan bulat untuk tidak bekerja sejak integer diinisialisasi ke nilai float mungkin tidak benar-benar menjadi nilai yang tepat tetapi pendekatan yang dekat. Tetapi bahkan kemudian, saya terkejut dengan hasil yang saya dapatkan.

Adakah yang punya solusi untuk masalah ini atau haruskah saya meningkatkan CPU saya untuk mendapatkan dukungan AVX2 mengaktifkan ini?


5
2017-12-11 19:03


asal


Jawaban:


Tes pertama bekerja secara tidak sengaja.

1 sebagai float adalah 0x3f800000, 2 adalah 0x40000000. Secara umum, itu tidak akan berhasil dengan cara itu.

Tetapi Anda benar-benar dapat melakukannya, Anda hanya perlu memastikan bahwa Anda bekerja dengan pola bit yang tepat. Jangan mengonversi bilangan bulat Anda ke pelampung - menafsirkan ulang-cast mereka. Itu sesuai dengan intrinsik seperti _mm256_castsi256_ps, atau menyimpan int Anda ke memori dan membacanya sebagai pelampung (yang tidak akan mengubahnya, pada umumnya hanya operasi matematika yang peduli tentang apa yang mengapung berarti, sisanya bekerja dengan pola bit mentah, periksa daftar pengecualian yang dapat dibuat oleh sebuah instruksi untuk memastikan).


7
2017-12-11 19:12



Anda tidak perlu AVX2 untuk menggunakan beban integer AVX dan operasi penyimpanan: lihat panduan intrinsik intel. Jadi Anda dapat memuat bilangan bulat menggunakan AVX, menafsirkan ulang-cast untuk mengapung, menggunakan operasi bitwise float, dan kemudian menafsirkan kembali-cast kembali ke int. Reinterpretasi-cast tidak menghasilkan instruksi, mereka hanya membuat compiler bahagia. Coba ini:

//compiled and ran on an Ivy Bridge system with AVX but without AVX2
#include <stdio.h>
#include <immintrin.h>
int main() {
    int a[8] = {0, 2, 4, 6, 8, 10, 12, 14};
    int b[8] = {1, 1, 1, 1, 1,  1,  1,  1};
    int c[8];

    __m256i a8 = _mm256_loadu_si256((__m256i*)a);
    __m256i b8 = _mm256_loadu_si256((__m256i*)b);
    __m256i c8 = _mm256_castps_si256(
        _mm256_or_ps(_mm256_castsi256_ps(a8), _mm256_castsi256_ps(b8)));
    _mm256_storeu_si256((__m256i*)c, c8);
    for(int i=0; i<8; i++) printf("%d ", c[i]); printf("\n");
    //output: 1 3 5 7 9 11 13 15
}

Tentu saja, sebagai Mistik menunjukkan ini mungkin tidak layak dilakukan tetapi itu tidak berarti Anda tidak dapat melakukannya.


4
2017-12-11 20:19