Datei:Haswell Apfelmännchen per Core.png

Originaldatei(3.129 × 2.245 Pixel, Dateigröße: 184 KB, MIME-Typ: image/png)

Diese Datei und die Informationen unter dem roten Trennstrich werden aus dem zentralen Medienarchiv Wikimedia Commons eingebunden.

Zur Beschreibungsseite auf Commons


Beschreibung

Beschreibung
English: Possible Parallelization of the Mandelbrot Set Calculation within a Haswell Core i7 per Core. You can see that up to 128 calculation (in total 16 instructions divided on two threads) can be executed per Core. On a Haswell Core i7-5960X this can be up to 1024 parallel calculations per CPU, on a Haswell Xeon E7-8890 v3 up to 2304 parallel calculations. Modern CPUs are far beyond from being non-parallel.
Datum
Quelle Eigenes Werk
Urheber Frank Klemm

Basic core ...

And yes, this code is on a Dual Xeon 18 core Haswell about 5 million times faster than on my 386 with a 387...

typedef union
{
    __m128d           V2  [  1];
    __m128            V4  [  1];
    __m128i           I   [  1];
    double            f64 [  2];
    float             f32 [  4];
    unsigned __int64  ui64[  2];
    unsigned __int32  ui32[  4];
    unsigned __int16  ui16[  8];
    unsigned __int8   ui8 [ 16];
    signed   __int64  i64 [  2];
    signed   __int32  i32 [  4];
    signed   __int16  i16 [  8];
    signed   __int8   i8  [ 16];
} _128;

typedef union
{
    __m256d           V4  [  1];
    __m256            V8  [  1];
    __m256i           II  [  1];
    __m128i           I   [  2];
    double            f64 [  4];
    float             f32 [  8];
    unsigned __int64  ui64[  4];
    unsigned __int32  ui32[  8];
    unsigned __int16  ui16[ 16];
    unsigned __int8   ui8 [ 32];
    signed   __int64  i64 [  4];
    signed   __int32  i32 [  8];
    signed   __int16  i16 [ 16];
    signed   __int8   i8  [ 32];
} _256;

typedef union
{
    _128              U128[  4];
    _256              U256[  2];
    __m256d           V4  [  2];
    __m256            V8  [  2];
    __m256i           II  [  2];
    __m128i           I   [  4];
    double            f64 [  8];
    float             f32 [ 16];
    unsigned __int64  ui64[  8];
    unsigned __int32  ui32[  4];
    unsigned __int16  ui16[ 32];
    unsigned __int8   ui8 [ 64];
    signed   __int64  i64 [  8];
    signed   __int32  i32 [ 16];
    signed   __int16  i16 [ 32];
    signed   __int8   i8  [ 64];
} _512;

typedef union
{
    _128              U128[  8];
    _256              U256[  4];
    _512              U512[  2];
    __m256d           V4  [  4];
    __m256            V8  [  4];
    __m256i           II  [  4];
    __m128i           I   [  8];
    double            f64 [ 16];
    float             f32 [ 32];
    unsigned __int64  ui64[ 16];
    unsigned __int32  ui32[  8];
    unsigned __int16  ui16[ 64];
    unsigned __int8   ui8 [128];
    signed   __int64  i64 [ 16];
    signed   __int32  i32 [ 32];
    signed   __int16  i16 [ 64];
    signed   __int8   i8  [128];
} _1024;

// im = 2*re*im   + imadd
// re = re2 - im2 + readd
#define JULIA_1                             \
    im[0] = _mm256_add_ps (im[0], im[0]);         \
    im[1] = _mm256_add_ps (im[1], im[1]);         \
    im[0] = _mm256_fmadd_ps (im[0], re[0], imagadd->V8[0]);   \
    im[1] = _mm256_fmadd_ps (im[1], re[1], imagadd->V8[1]);   \
    re[0] = _mm256_sub_ps (re2[0], im2[0]);       \
    re[1] = _mm256_sub_ps (re2[1], im2[1]);       \
    re[0] = _mm256_add_ps (re[0], realadd->V8[0]);      \
    re[1] = _mm256_add_ps (re[1], realadd->V8[1])

// repim = re+im
// remim = re-im
// im = 2*re*im     - readd
// re = repim*remim - imadd
#define JULIA_2                             \
    repim[0] = _mm256_add_ps (re[0], im[0]);      \
    repim[1] = _mm256_add_ps (re[1], im[1]);      \
    remim[0] = _mm256_sub_ps (re[0], im[0]);      \
    remim[1] = _mm256_sub_ps (re[1], im[1]);      \
    im[0] = _mm256_add_ps (im[0], im[0]);         \
    im[1] = _mm256_add_ps (im[1], im[1]);         \
    im[0] = _mm256_fmadd_ps (im[0], re[0], imagadd->V8[0]);           \
    im[1] = _mm256_fmadd_ps (im[1], re[1], imagadd->V8[1]);           \
    re[0] = _mm256_fmadd_ps (repim[0], remim[0], realadd->V8[0]);     \
    re[1] = _mm256_fmadd_ps (repim[1], remim[1], realadd->V8[1])

// re2 = re*re
// im2 = im*im
// sum = re2 + im2
#define JULIA_3                             \
    re2[0] = _mm256_mul_ps (re[0], re[0]);        \
    re2[1] = _mm256_mul_ps (re[1], re[1]);        \
    im2[0] = _mm256_mul_ps (im[0], im[0]);        \
    im2[1] = _mm256_mul_ps (im[1], im[1]);        \
    sum[0] = _mm256_add_ps (re2[0], im2[0]);      \
    sum[1] = _mm256_add_ps (re2[1], im2[1])

static void
Julia16x32_Mac (
             _512* const  dst,
       const _512* const  real_begin,
       const _512* const  imag_begin,
       const _512* const  realadd,
       const _512* const  imagadd,
       const __int32      maxiter)
{
    __int32       cnt    = maxiter;
    __m256        re[2]    = { real_begin->V8[0], real_begin->V8[1] };
    __m256        im[2]    = { imag_begin->V8[0], imag_begin->V8[1] };
    __m256        repim[2];
    __m256        remim[2];
    __m256        result[2] = { flt_c0 };
    __m256        add[2] = { flt_c1, flt_c1 };

    __m256        re2[2];
    __m256        im2[2];
    __m256        sum[2];
    __m256i       cmp[2];
    goto check1;

loop1:
    cnt -= 5;
    JULIA_1;

    JULIA_2;
    JULIA_2;
    JULIA_2;
    JULIA_2;
    result[0] = _mm256_add_ps (result[0], flt_c5);

check1:
    JULIA_3;
    cmp[0] = _mm256_castps_si256 (_mm256_cmp_ps (sum[0], flt_c4, _CMP_LT_OQ));
    cmp[1] = _mm256_castps_si256 (_mm256_cmp_ps (sum[1], flt_c4, _CMP_LT_OQ));

    cmp[0] = _mm256_castps_si256 (_mm256_and_ps (_mm256_castsi256_ps(cmp[0]), _mm256_castsi256_ps(cmp[1])));

    if (cnt >= 5 && (cmp[0].m256i_u64[0] & cmp[0].m256i_u64[1] & cmp[0].m256i_u64[2] & cmp[0].m256i_u64[3]) == 0xFFFFFFFFFFFFFFFF)
        goto loop1;

    result[1] = result[0];
    goto check2;

loop2:
    cnt -= 1;
    JULIA_1;

    result[0] = _mm256_add_ps (result[0], add[0]);
    result[1] = _mm256_add_ps (result[1], add[1]);

    JULIA_3;
check2:
    cmp[0] = _mm256_castps_si256 (_mm256_cmp_ps (sum[0], flt_inf, _CMP_LT_OQ));
    cmp[1] = _mm256_castps_si256 (_mm256_cmp_ps (sum[1], flt_inf, _CMP_LT_OQ));
    add[0] = _mm256_and_ps (add[0], _mm256_castsi256_ps (cmp[0]));
    add[1] = _mm256_and_ps (add[1], _mm256_castsi256_ps (cmp[1]));

    cmp[0] = _mm256_castps_si256 (_mm256_or_ps (_mm256_castsi256_ps(cmp[0]), _mm256_castsi256_ps(cmp[1])));

    if (cnt >= 1  &&  _mm256_testz_pd (_mm256_castsi256_pd(cmp[0]), _mm256_castsi256_pd(cmp[0])) == 0)
        goto loop2;

    (dst->II)[0] =  _mm256_cvttps_epi32 (result[0]);
    (dst->II)[1] =  _mm256_cvttps_epi32 (result[1]);
}

#undef JULIA_1
#undef JULIA_2
#undef JULIA_3

Lizenz

Ich, der Urheber dieses Werkes, veröffentliche es unter der folgenden Lizenz:
w:de:Creative Commons
Namensnennung Weitergabe unter gleichen Bedingungen
Dieses Werk darf von dir
  • verbreitet werden – vervielfältigt, verbreitet und öffentlich zugänglich gemacht werden
  • neu zusammengestellt werden – abgewandelt und bearbeitet werden
Zu den folgenden Bedingungen:
  • Namensnennung – Du musst angemessene Urheber- und Rechteangaben machen, einen Link zur Lizenz beifügen und angeben, ob Änderungen vorgenommen wurden. Diese Angaben dürfen in jeder angemessenen Art und Weise gemacht werden, allerdings nicht so, dass der Eindruck entsteht, der Lizenzgeber unterstütze gerade dich oder deine Nutzung besonders.
  • Weitergabe unter gleichen Bedingungen – Wenn du das Material wiedermischst, transformierst oder darauf aufbaust, musst du deine Beiträge unter der gleichen oder einer kompatiblen Lizenz wie das Original verbreiten.

Kurzbeschreibungen

Ergänze eine einzeilige Erklärung, was diese Datei darstellt.

In dieser Datei abgebildete Objekte

Motiv

Urheber

Einige Werte ohne einen Wikidata-Eintrag

Autor (Text): Frank Klemm
Wikimedia-Benutzername: Frank Klemm

Urheberrechtsstatus

urheberrechtlich geschützt

Lizenz

Creative Commons Namensnennung – Weitergabe unter gleichen Bedingungen 4.0 international

Datum der Gründung, Erstellung, Entstehung, Erbauung

9. August 2017

Quelle der Datei

durch Hochlader/in erstelltes Original

Dateiversionen

Klicke auf einen Zeitpunkt, um diese Version zu laden.

Version vomVorschaubildMaßeBenutzerKommentar
aktuell01:56, 9. Aug. 2017Vorschaubild der Version vom 01:56, 9. Aug. 20173.129 × 2.245 (184 KB)Frank KlemmUser created page with UploadWizard

Die folgende Seite verwendet diese Datei: