신경망을 구현하는 동안 데이터 집합 배열에 대해 연속 된 단일 블록으로 메모리를 할당하면 실행 시간이 여러 번 증가한다는 것을 알게되었습니다. -march=native -Ofast
(시도 GCC와 연타)로 컴파일 할 때 여기에 대용량 행렬 곱하기 연속 메모리 할당시 훨씬 느림
float** alloc_2d_float(int rows, int cols, int contiguous)
{
int i;
float** array = malloc(rows * sizeof(float*));
if(contiguous)
{
float* data = malloc(rows*cols*sizeof(float));
assert(data && "Can't allocate contiguous memory");
for(i=0; i<rows; i++)
array[i] = &(data[cols * i]);
}
else
for(i=0; i<rows; i++)
{
array[i] = malloc(cols * sizeof(float));
assert(array[i] && "Can't allocate memory");
}
return array;
}
결과를 다음과 같습니다 :
https://github.com/michaelklachko/NN/blob/master/test.c
: 여기
[email protected]:~/NN$ time ./test 300 1 0
Multiplying (100000, 1000) and (300, 1000) arrays 1 times, noncontiguous memory allocation.
Allocating memory: 0.2 seconds
Initializing arrays: 0.8 seconds
Dot product: 3.3 seconds
real 0m4.296s
user 0m4.108s
sys 0m0.188s
[email protected]:~/NN$ time ./test 300 1 1
Multiplying (100000, 1000) and (300, 1000) arrays 1 times, contiguous memory allocation.
Allocating memory: 0.0 seconds
Initializing arrays: 40.3 seconds
Dot product: 13.5 seconds
real 0m53.817s
user 0m4.204s
sys 0m49.664s
코드 것
는 메모리 할당이 두 가지 방법을 비교
초기화 및 내적 모두 연속 메모리의 경우 속도가 느립니다.
나는 반대로 예상했다. 인접한 메모리 블록은 많은 수의 분리 된 작은 블록보다 캐시 친화적이어야한다. 또는 적어도 성능면에서 유사해야합니다 (이 컴퓨터의 RAM 용량은 64GB이며 90 %는 사용되지 않습니다).
편집 : 여기에 압축 자체에 포함 된 코드는 (나는 아직도 측정 및 서식 문시킨 대신 github의 버전을 사용하는 것이 좋습니다) : 당신의 능력 또는 장애로 실행하는 것 같은
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float** alloc_2d_float(int rows, int cols, int contiguous){
int i;
float** array = malloc(rows * sizeof(float*));
if(contiguous){
float* data = malloc(rows*cols*sizeof(float));
for(i=0; i<rows; i++)
array[i] = &(data[cols * i]);
}
else
for(i=0; i<rows; i++)
array[i] = malloc(cols * sizeof(float));
return array;
}
void initialize(float** array, int dim1, int dim2){
srand(time(NULL));
int i, j;
for(i=0; i<dim1; i++)
for(j=0; j<dim2; j++)
array[i][j] = rand()/RAND_MAX;
}
int main(){
int i,j,k, dim1=100000, dim2=1000, dim3=300;
int contiguous=0;
float temp;
float** array1 = alloc_2d_float(dim1, dim2, contiguous);
float** array2 = alloc_2d_float(dim3, dim2, contiguous);
float** result = alloc_2d_float(dim1, dim3, contiguous);
initialize(array1, dim1, dim2);
initialize(array2, dim3, dim2);
for(i=0; i<dim1; i++)
for(k=0; k<dim3; k++){
temp = 0;
for(j=0; j<dim2; j++)
temp += array1[i][j] * array2[k][j];
result[i][k] = temp;
}
}
더 2D 없다 0.0 초 초기화 배열 : 메모리를 할당 배열에 배열하십시오. 'float ** '과 같은 것은 2D 배열이 아니며, 하나의 배열을 가리 키지도 않습니다. 2D 배열을 사용하십시오. [ask]를보고 [mcve]를 제공하십시오. – Olaf
@Olaf : 당신은 무엇을 의미합니까? 내가 배열 배열을 만드는거야, 안 그래? – MichaelSB
아니, 그렇지 않다! 'float' **에 대한 포인터 배열을 만듭니다. 아주 다른 데이터 유형. 다차원 배열에 대해 배우는 것이 좋습니다.당신이 사용하는 것은 이것과는 거리가 멀고 아마도 당신의 문제 일 것입니다. – Olaf