는 여기에 내가 큰 프로젝트에서 철수 한 코드의 실제 조각입니다. (미안하지만, 내가 발견 할 수있는 가장 빠른 것은 프리 페치에서 눈에 띄는 속도 향상이 있습니다.) 이 코드는 매우 큰 데이터 전치를 수행합니다.
이 예에서는 GCC에서 방출하는 것과 동일한 SSE 프리 페치 지침을 사용합니다.
이 예제를 실행하려면 x64의 경우이 파일을 컴파일해야하고 4GB 이상의 메모리가 있어야합니다. 더 작은 데이터 크기로 실행할 수는 있지만 너무 빠르다. 내가 ENABLE_PREFETCH 활성화와 실행
#include <iostream>
using std::cout;
using std::endl;
#include <emmintrin.h>
#include <malloc.h>
#include <time.h>
#include <string.h>
#define ENABLE_PREFETCH
#define f_vector __m128d
#define i_ptr size_t
inline void swap_block(f_vector *A,f_vector *B,i_ptr L){
// To be super-optimized later.
f_vector *stop = A + L;
do{
f_vector tmpA = *A;
f_vector tmpB = *B;
*A++ = tmpB;
*B++ = tmpA;
}while (A < stop);
}
void transpose_even(f_vector *T,i_ptr block,i_ptr x){
// Transposes T.
// T contains x columns and x rows.
// Each unit is of size (block * sizeof(f_vector)) bytes.
//Conditions:
// - 0 < block
// - 1 < x
i_ptr row_size = block * x;
i_ptr iter_size = row_size + block;
// End of entire matrix.
f_vector *stop_T = T + row_size * x;
f_vector *end = stop_T - row_size;
// Iterate each row.
f_vector *y_iter = T;
do{
// Iterate each column.
f_vector *ptr_x = y_iter + block;
f_vector *ptr_y = y_iter + row_size;
do{
#ifdef ENABLE_PREFETCH
_mm_prefetch((char*)(ptr_y + row_size),_MM_HINT_T0);
#endif
swap_block(ptr_x,ptr_y,block);
ptr_x += block;
ptr_y += row_size;
}while (ptr_y < stop_T);
y_iter += iter_size;
}while (y_iter < end);
}
int main(){
i_ptr dimension = 4096;
i_ptr block = 16;
i_ptr words = block * dimension * dimension;
i_ptr bytes = words * sizeof(f_vector);
cout << "bytes = " << bytes << endl;
// system("pause");
f_vector *T = (f_vector*)_mm_malloc(bytes,16);
if (T == NULL){
cout << "Memory Allocation Failure" << endl;
system("pause");
exit(1);
}
memset(T,0,bytes);
// Perform in-place data transpose
cout << "Starting Data Transpose... ";
clock_t start = clock();
transpose_even(T,block,dimension);
clock_t end = clock();
cout << "Done" << endl;
cout << "Time: " << (double)(end - start)/CLOCKS_PER_SEC << " seconds" << endl;
_mm_free(T);
system("pause");
}
, 이것은 출력입니다 :
bytes = 4294967296
Starting Data Transpose... Done
Time: 0.822 seconds
Press any key to continue . . .
은 그래서 거기 :
bytes = 4294967296
Starting Data Transpose... Done
Time: 0.725 seconds
Press any key to continue . . .
내가 ENABLE_PREFETCH 장애인과 실행, 이것은 출력 프리 페칭에서 13 %의 속도 향상.
편집 :
가 여기 좀 더 결과 :
Operating System: Windows 7 Professional/Ultimate
Compiler: Visual Studio 2010 SP1
Compile Mode: x64 Release
Intel Core i7 860 @ 2.8 GHz, 8 GB DDR3 @ 1333 MHz
Prefetch : 0.868
No Prefetch: 0.960
Intel Core i7 920 @ 3.5 GHz, 12 GB DDR3 @ 1333 MHz
Prefetch : 0.725
No Prefetch: 0.822
Intel Core i7 2600K @ 4.6 GHz, 16 GB DDR3 @ 1333 MHz
Prefetch : 0.718
No Prefetch: 0.796
2 x Intel Xeon X5482 @ 3.2 GHz, 64 GB DDR2 @ 800 MHz
Prefetch : 2.273
No Prefetch: 2.666
흥미 롭습니다. 불행히도 테스트 한 2 대의 컴퓨터 (Macbook Pro는 "Core 2 Duo"이고 Linux 컴퓨터는 "Quad-Core AMD Opteron Processor 2376")에서는 두 버전 사이에 큰 차이가 없었습니다. 캐시 크기와 관련이 있다고 생각합니다.이 두 가지보다 우수한 컴퓨터가있는 것 같습니다. 어떻게 생각해? –
내 컴퓨터는 Core i7 920 @ 3.5GHz입니다. 8MB L3 캐시. 이 10 %의 속도 향상은 내가 테스트 한 다른 3 대의 머신, 즉 Core i7 2600K @ 4.6GHz와 2x Xeon X5482 @ 3.2GHz에서 거의 일치합니다. 하지만 랩톱이나 AMD 컴퓨터에서 테스트 한 적이 없다는 것을 인정합니다. – Mysticial
방금 테스트 한 4 대의 모든 컴퓨터에서 벤치 마크를 통해 내 대답을 편집했습니다. 모든 인텔 데스크탑/워크 스테이션입니다. 그래서 그것이 이유 일 수 있습니다. 세 번째 요점이 맞는지 테스트하지 않았습니다. 메모리 액세스로 대체하면 동일한 결과가 발생할 수 있습니다. – Mysticial