Warum ist mein Simd Vector Plus und setzt langsamer als die Verwendung von std :: transform und std :: plus <t> - mache C++

Programme in C++. Entwicklerforum
Anonymous
 Warum ist mein Simd Vector Plus und setzt langsamer als die Verwendung von std :: transform und std :: plus <t> - mache

Post by Anonymous »

Neu in Simd Bitte gehen Sie mir leicht, wenn ich Fehler gemacht habe. Mein Prozessor ist der 11. Gen Intel (R) Core (TM) I7-11370H @ 3.30GHz < /p>
Bevor Sie AXV verwenden

Code: Select all

bool supportsAVX()
{
int cpuInfo[4] = { 0 };
__cpuid(cpuInfo, 1);
return (cpuInfo[2] & (1 
Bevor die SIMD -Add -Funktion für Vektor implementiert wurde, habe ich sichergestellt, dass der Vektorpuffer 32 Byte mithilfe der Implemenation hier ausgerichtet ist (Implementierung eines Allocators): Moderner Ansatz zur Erstellung von STD :: Vektor -Zuordnungen ausgerichtetem Speicher. Der Demo -Code aus dieser Antwort ist hier: https://godbolt.org/z/pg5ph7936
Also habe ich einen 32 -Byte -Vektor für AVX wie unten definiert.  
template
using Aligned32Vector = std::vector;

< /code>
Dies ist meine SIMD -Funktion hinzufügen: < /p>
#include "aligned_vector.hpp"
#include   // For SSE/AVX intrinsics

void simd_add_sd_float_avx(const simd_util::Aligned32Vector& a, const simd_util::Aligned32Vector& b, simd_util::Aligned32Vector& c)
{
size_t const total_size = a.size();
constexpr size_t working_width = 32 / sizeof(double);

size_t i = 0;

// AVX SIMD loop
for (; i < total_size - working_width; i += working_width)
{  // Process 4 double at a time
// Load
__m256d va = _mm256_load_pd(&a[i]);  // Load 4 double
__m256d vb = _mm256_load_pd(&b[i]);  // Load 4 double

// Perform SIMD addition
__m256d vsum = _mm256_add_pd(va, vb);  // Add 4 double in parallel

// Store the result back into the 'result' array
_mm256_store_pd(&c[i], vsum);  // Store 4 double
}

// Handle leftovers
if (i < total_size)
{
size_t remaining = total_size - i;
alignas(32) double mask_data[4] = { 0.0 };

__m256d mask = _mm256_set_pd(
remaining > 3 ? -1.0 : 0.0,
remaining > 2 ? -1.0 : 0.0,
remaining > 1 ? -1.0 : 0.0,
remaining > 0 ? -1.0 : 0.0
);
// over reading and adding, but who cares we good as long as we dont use them
__m256d va = _mm256_loadu_pd(&a[i]);
__m256d vb = _mm256_loadu_pd(&b[i]);
__m256d vr = _mm256_add_pd(va, vb);
__m256d existing = _mm256_setzero_pd(); // Set to zeros
__m256d blended = _mm256_blendv_pd(existing, vr, mask);

// Scalar write-back
alignas(32) double temp[4];
_mm256_storeu_pd(temp, blended);
for (int j = 0; j < remaining; ++j)
{
c[i + j] = temp[j];
}
}
}
< /code>
Dies ist meine einfache Funktion mit addieren mit std :: vector: < /p>
#include
#include

void add_vector_float_normal(const std::vector& a, const std::vector& b, std::vector& c)
{
std::transform(a.begin(), a.end(), b.begin(), c.begin(), std::plus());
}

< /code>
Mein Testfall ist einfach, mach 2 Vektor der Größe 1000000, Wert 1, addiere sie dann einen dritten Vektor derselben Größe und vergleichen ihre Wandzeit mit Chrono, mit einer Iteration von 10000.std::vector a(1000000,1);
std::vector b(1000000,1);
std::vector c(1000000,0);

auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i)
{
add_vector_float_normal(a,b,c);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(end - start);
double average_time_us = static_cast(duration.count()) / iterations;
< /code>
SIMD: < /p>
simd_util::Aligned32Vector a(1000000, 1);
simd_util::Aligned32Vector b(1000000, 1);
simd_util::Aligned32Vector c(1000000, 0);

auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i)
{
simd_add_sd_float_avx(a, b, c);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast(end - start);
double average_time_us = static_cast(duration.count()) / iterations;
Der Skalar -Lauf scheint immer die SIMD -Funktion auszuführen:

. Scalar? < /p>
mache ich etwas falsches? Liegt es daran, dass mein restlicher Handling nicht effizient ist?

Code: Select all

/permissive- /ifcOutput "x64\Release\" /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"x64\Release\vc143.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /std:c17 /Gd /Oi /MD /std:c++20 /FC /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\simd_matrix.pch" /diagnostics:column
< /code>
In meiner vcxproj -Datei ist es: < /p>
  

Level3
true
true
true
NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpp20
stdc17


Console
true
true
true


Bearbeiten 2
Ich hätte dies wahrscheinlich zuerst tun sollen, was die Kommentare vorgeschlagen haben, die ich mir den ASM angesehen habe, der von meinem Compiler generiert wurde. Für den einfachen STD :: Transformationstest wird es Vektorisierungen /SIMD -Simd vom Compiler mit /O2 -Flag erzeugt. Obwohl ich weiß, dass mein PC AVX unterstützen sollte, nicht sicher, warum es die kleineren SSE -Register verwendet?

Code: Select all

$LL33@add_vector:
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\xutility
; Line 501
movups  xmm0, XMMWORD PTR [rcx]
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\algorithm
; Line 3763
add rsi, 8
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\xutility
; Line 501
movups  xmm1, XMMWORD PTR [rax]
addpd   xmm1, xmm0
movups  xmm0, XMMWORD PTR [rcx+16]
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\algorithm
; Line 3764
movups  XMMWORD PTR [rdx], xmm1
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\xutility
; Line 501
movups  xmm1, XMMWORD PTR [rax+16]
addpd   xmm1, xmm0
movups  xmm0, XMMWORD PTR [rcx+32]
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\algorithm
; Line 3764
movups  XMMWORD PTR [rdx+16], xmm1
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\xutility
; Line 501
movups  xmm1, XMMWORD PTR [rax+32]
addpd   xmm1, xmm0
movups  xmm0, XMMWORD PTR [rcx+48]
; File C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.42.34433\include\algorithm
Bearbeiten 3
Die Kommentare von @Petercordes haben sehr geholfen, und wie er vorgeschlagen hat, wird im MSVC generierten Code eine Schleife abrollt! Ich werde versuchen, dies für meine AVX -Implementierung zu implementieren und zu sehen, ob ich den Unterschied sehen kann!

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post