在矩阵乘法 C++ SIMD 编程中检测到 Stack Smashing
Stack Smashing Detected in Matrix Multiplication C++ SIMD Programming
我刚刚使用 C++ 学习了 simd 编程,我可以轻松地执行加法和减法,但我发现矩阵乘法有问题。
当我编译它时使用:
gcc -o auto-vector auto-vector.cpp -lstdc++
它已编译,但是当我尝试 运行 它时,它说:
经过时间:3e-06 秒
* 检测到堆栈粉碎 *:已终止
它说检测到堆栈粉碎但它也测量经过的时间。
我的代码编译了吗?
//gcc -o auto-vector auto-vector.cpp -lstdc++
#include "xmmintrin.h"
#include <chrono> // for high_resolution_clock
#include <iostream>
int main()
{
float A[4][4] = {{16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}};
float B[4][4] = {{16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}};
float C[4][4] = {};
__m128 a_vec, b_vec, c_vec;
int N = 4;
// Record start time
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
c_vec = _mm_set1_ps(0);
for (int k = 0; k < N; k++)
{
a_vec = _mm_set1_ps(A[i][k]);
b_vec = _mm_loadu_ps(&B[k][j]);
c_vec = _mm_add_ps(_mm_mul_ps(a_vec, b_vec), c_vec);
}
_mm_storeu_ps(&C[i][j], c_vec);
}
}
// Record end time
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Elapsed time: " << elapsed.count() << " s\n";
return 0;
}
这意味着你存储了一个堆栈数组的末尾,你很幸运它在你的堆栈帧的顶部所以 -fstack-protector-strong
可以为你捕获错误而不是仅仅踩到其他本地人.
例如C[3][3]
的 16 字节存储触及 C[3][3 .. 7]
.
您正在对 j
进行自动矢量化,但您忘记将 j
递增 4 而不是 1,并使用 j < N - 3
作为循环边界.
此外,如果您想要有意义的计时结果,请确保使用 gcc -O3
进行编译。或者最好是 gcc -O3 -march=native -ffast-math -flto
和 -fprofile-generate
/ -fprofile-use
.
此外,您正在测试 手动 矢量化,但您的评论说 "auto-vector".
编码风格:在您第一次使用时声明您的 __m128
变量。喜欢
__m128 c_vec = _mm_setzero_ps();
我刚刚使用 C++ 学习了 simd 编程,我可以轻松地执行加法和减法,但我发现矩阵乘法有问题。
当我编译它时使用: gcc -o auto-vector auto-vector.cpp -lstdc++
它已编译,但是当我尝试 运行 它时,它说: 经过时间:3e-06 秒 * 检测到堆栈粉碎 *:已终止
它说检测到堆栈粉碎但它也测量经过的时间。
我的代码编译了吗?
//gcc -o auto-vector auto-vector.cpp -lstdc++
#include "xmmintrin.h"
#include <chrono> // for high_resolution_clock
#include <iostream>
int main()
{
float A[4][4] = {{16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}};
float B[4][4] = {{16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}, {16, 2, 77, 40}};
float C[4][4] = {};
__m128 a_vec, b_vec, c_vec;
int N = 4;
// Record start time
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
c_vec = _mm_set1_ps(0);
for (int k = 0; k < N; k++)
{
a_vec = _mm_set1_ps(A[i][k]);
b_vec = _mm_loadu_ps(&B[k][j]);
c_vec = _mm_add_ps(_mm_mul_ps(a_vec, b_vec), c_vec);
}
_mm_storeu_ps(&C[i][j], c_vec);
}
}
// Record end time
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = finish - start;
std::cout << "Elapsed time: " << elapsed.count() << " s\n";
return 0;
}
这意味着你存储了一个堆栈数组的末尾,你很幸运它在你的堆栈帧的顶部所以 -fstack-protector-strong
可以为你捕获错误而不是仅仅踩到其他本地人.
例如C[3][3]
的 16 字节存储触及 C[3][3 .. 7]
.
您正在对 j
进行自动矢量化,但您忘记将 j
递增 4 而不是 1,并使用 j < N - 3
作为循环边界.
此外,如果您想要有意义的计时结果,请确保使用 gcc -O3
进行编译。或者最好是 gcc -O3 -march=native -ffast-math -flto
和 -fprofile-generate
/ -fprofile-use
.
此外,您正在测试 手动 矢量化,但您的评论说 "auto-vector".
编码风格:在您第一次使用时声明您的 __m128
变量。喜欢
__m128 c_vec = _mm_setzero_ps();