2016-01-02 3 views
1

Я использую SSE для реализации умножения матрицы, и я получил Stack Overflow Exception при запуске кода. И stack overflow exception находится в chktsk.asmПочему я получаю переполнение стека здесь?

; Find next lower page and probe 
cs20: 
     sub  eax, _PAGESIZE_   ; decrease by PAGESIZE 
     test dword ptr [eax],eax  ; probe page. 
     jmp  short cs10 

_chkstk endp 

     end 

Это трудно обнаружить, где это неправильно, и мой код является:

main.cpp

#include "sse_matrix.h" 

int main(int argc, char* argv[]) 
{ 
    float left[size] = {0}; 
    float right[size] = {0}; 
    float result[size] = {0}; 
    // initialize value 
    for (int i = 0; i < dim; i ++) 
    { 
     for (int j = 0; j < dim; j ++) 
     { 
      left[i*dim + j] = j; 
      right[i*dim + j] = j; 
     } 

    } 
    //calculate the result 
    SSE_Matrix_Multiply(left, right, result); 
    /*for (int i = 0; i < dim; i ++) 
    { 
     for (int j = 0; j < dim; j ++) 
     { 
      cout << result[i * dim + j] << " "; 
     } 
     cout << endl; 
    }*/ 
    system("pause"); 

    return 0; 

} 

инклюдник:

#ifndef __SSE_MATRIX_H 
#define __SSE_MATRIX_H 

#include <iostream> 
using std::cin; 
using std::cout; 
using std::endl; 

#define dim 512 
#define size dim * dim 

struct Matrix_Info 
{ 
    float *A; 
    int ax, ay; 
    float *B; 
    int bx, by; 
    float *C; 
    int cx, cy; 
    int m; 
    int n; 
}; 

void Transpose_Matrix_SSE(float * matrix) 
{ 
    __m128 row1 = _mm_loadu_ps(&matrix[0*4]); 
    __m128 row2 = _mm_loadu_ps(&matrix[1*4]); 
    __m128 row3 = _mm_loadu_ps(&matrix[2*4]); 
    __m128 row4 = _mm_loadu_ps(&matrix[3*4]); 
    _MM_TRANSPOSE4_PS(row1, row2, row3, row4); 
    _mm_storeu_ps(&matrix[0*4], row1); 
    _mm_storeu_ps(&matrix[1*4], row2); 
    _mm_storeu_ps(&matrix[2*4], row3); 
    _mm_storeu_ps(&matrix[3*4], row4); 

} 

float * Shuffle_Matrix_Multiply(float * left, float * right) 
{ 
    __m128 _t1, _t2, _sum; 
    _sum = _mm_setzero_ps(); // set all value of _sum to zero 
    float _result[size] = {0}; 
    float _res[4] = {0}; 
    for (int i = 0; i < 4; i ++) 
    { 
     for (int j = 0; j < 4; j ++) 
     { 
      _t1 = _mm_loadu_ps(left + i * 4); 
      _t2 = _mm_loadu_ps(right + j * 4); 
      _sum = _mm_mul_ps(_t1, _t2); 
      _mm_storeu_ps(_res, _sum); 
      _result[i * 4 + j] = _res[0] + _res[1] + _res[2] + _res[3]; 
     } 
    } 
    return _result; 
} 

float * SSE_4_Matrix(struct Matrix_Info * my_info) 
{ 
    int m = my_info->m; 
    int n = my_info->n; 
    int ax = my_info->ax; 
    int ay = my_info->ay; 
    int bx = my_info->bx; 
    int by = my_info->by; 
    //1. split Matrix A and Matrix B 
    float * _a = new float[16]; 
    float * _b = new float[16]; 
    for (int i = 0; i < m; i ++) 
    { 
     for (int j = 0; j < m; j ++) 
     { 
      _a[i*m + j] = *(my_info->A + (i + ax) * n + j + ay); 
      _b[i*m + j] = *(my_info->B + (i + bx) * n + j + by); 
     } 
    } 
    //2. transpose Matrix B 
    Transpose_Matrix_SSE(_b); 
    //3. calculate result and return a float pointer 
    return Shuffle_Matrix_Multiply(_a, _b); 
} 

int Matrix_Multiply(struct Matrix_Info * my_info) 
{ 
    int m = my_info->m; 
    int n = my_info->n; 
    int cx = my_info->cx; 
    int cy = my_info->cy; 
    for (int i = 0; i < m; i ++) 
    { 
     for (int j = 0; j < m; j ++) 
     { 
      *(my_info->C + (i + cx) * n + j + cy) += SSE_4_Matrix(my_info)[i*m + j]; 
     } 
    } 
    return 0; 
} 

void SSE_Matrix_Multiply(float *left, float *right, float *result) 
{ 
    struct Matrix_Info my_info; 
    my_info.A = left; 
    my_info.B = right; 
    my_info.C = result; 
    my_info.n = dim; 
    my_info.m = 4; 

    // Matrix A row:i, column:j 
    for (int i = 0; i < dim; i += 4) 
    { 
     for (int j = 0; j < dim; j += 4) 
     { 
      // Matrix B row:j column:k 
      for (int k = 0; k < dim; k += 4) 
      { 
       my_info.ax = i; 
       my_info.ay = j; 
       my_info.bx = j; 
       my_info.by = k; 
       my_info.cx = i; 
       my_info.cy = k; 
       Matrix_Multiply(&my_info); 
      } 
     } 
    } 
} 

#endif 

Когда dim (размер матрицы) включен в файл include 4, 8, 16, 32, 64, 128 and 256, Stack Overflow Exception не произойдет. Но, когда dim будет 512 или больше, произойдет Stack Overflow Exception.

Моей ОС является Windows 10 и IDE является Visual Studio 2012.

Что действительно заставляет меня чувствовать себя смущенным, так это то, что когда я сделал точку останова в main.cpp по адресу #include "sse_matrix.h", и когда он запускается, и затем, это происходит Stack Overflow Exception. Я думаю, что в моих кодах нет синтаксической ошибки или логической ошибки. Но я не знаю, как это исправить.

+2

Я подозреваю, что переполнение стека появляется здесь на самом деле: 'плавать _result [размер] = {0};' 'размер '(262144) просто не помещается в стек. –

+0

@ πάνταῥεῖ, вы ставите, я написал простую программу 'int main() {float matrix [512 * 512] = {0}; return 0;} 'и произошло одно и то же исключение. –

+2

Несомненно, как уже упоминалось, он просто не вписывается в стек. Используйте 'std :: vector ' вместо того, чтобы память управлялась в куче. –

ответ

7

Вы #define ING size быть dim * dim после того как вы #define dim 512, так size является 262144. Затем вы положите float _result[size] в стек. Большинство стеков меньше, чем 262,144 * sizeof(float).

Как @ πάντα ῥεῖ говорит, вы, вероятно, хотите что-то больше похоже:

std::vector<float> _result(size, 0); 

что путь ваш 262144 * sizeof(float) часть памяти помещается в куче и управляется для вас (что гораздо лучше, чем распределение и де-выделения этой памяти - даже лучше, чем умный указатель, потому что std::vector будет адаптироваться к изменениям в размере для вас).

И как @ Basile Starynkevitch указывает, вы не хотите:

#define size dim * dim 

потому что dim * dim текст будет просто заменить size и легко может привести к ошибкам синтаксиса или хуже.

Лучше:

#define size (dim * dim) 

И гораздо лучше:

constexpr size_t dim = 512; 
constexpr size_t size = dim * dim;