16 FFT가 매우 작습니다. 당신이 발견 할 수있는 것은 64라고 말하는 것보다 작은 FFT는 최상의 성능을 얻기 위해 루프가없는 하드 코딩 된 어셈블러가 될 것입니다. 이는 명령 세트, 컴파일러 최적화, 심지어 64 비트 또는 32 비트 워드의 변형에 매우 취약 할 수 있음을 의미합니다.
2의 거듭 제곱에서 16 -> 1048576의 FFT 크기 테스트를 실행하면 어떻게됩니까? Linux에서 특정 하드 코딩 된 asm 루틴이 컴퓨터에 최적화되어 있지 않을 수도 있지만 특정 크기의 Windows 구현에서는 운이 좋았을 수도 있습니다. 이 범위의 모든 크기를 비교해 보면 Linux와 Windows의 성능을보다 잘 파악할 수 있습니다.
FFTW를 보정 해 보셨습니까? FFTW를 처음 실행하면 컴퓨터 당 가장 빠른 구현을 추측하지만 특수 명령어 세트 나 특정 크기의 캐시 또는 기타 프로세서 기능이있는 경우 실행 속도에 큰 영향을 미칠 수 있습니다. 결과적으로 캘리브레이션을 수행하면 다양한 FFT 루틴의 속도를 테스트하고 특정 하드웨어에 가장 빠른 크기를 선택할 수 있습니다. 교정에는 반복적으로 계획을 계산하고 생성 된 FFTW "지혜"파일을 저장하는 작업이 포함됩니다. 저장된 교정 데이터 (이것은 긴 과정입니다)를 다시 사용할 수 있습니다. 소프트웨어가 시작되고 매번 파일을 다시 사용할 때 한 번 해보는 것이 좋습니다. 교정 후 특정 크기에 대해 4-10 배 성능 향상을 나타 냈습니다!
다음은 특정 크기에 대해 FFTW를 보정하는 데 사용한 코드 스 니펫입니다. 이 코드는 필자가 작업 한 DSP 라이브러리에서 그대로 붙여 넣어 졌으므로 일부 함수 호출은 내 라이브러리에만 적용됩니다. FFTW 특정 전화가 도움이되기를 바랍니다.
는
// Calibration FFTW
void DSP::forceCalibration(void)
{
// Try to import FFTw Wisdom for fast plan creation
FILE *fftw_wisdom = fopen("DSPDLL.ftw", "r");
// If wisdom does not exist, ask user to calibrate
if (fftw_wisdom == 0)
{
int iStatus2 = AfxMessageBox("FFTw not calibrated on this machine."\
"Would you like to perform a one-time calibration?\n\n"\
"Note:\tMay take 40 minutes (on P4 3GHz), but speeds all subsequent FFT-based filtering & convolution by up to 100%.\n"\
"\tResults are saved to disk (DSPDLL.ftw) and need only be performed once per machine.\n\n"\
"\tMAKE SURE YOU REALLY WANT TO DO THIS, THERE IS NO WAY TO CANCEL CALIBRATION PART-WAY!",
MB_YESNO | MB_ICONSTOP, 0);
if (iStatus2 == IDYES)
{
// Perform calibration for all powers of 2 from 8 to 4194304
// (most heavily used FFTs - for signal processing)
AfxMessageBox("About to perform calibration.\n"\
"Close all programs, turn off your screensaver and do not move the mouse in this time!\n"\
"Note:\tThis program will appear to be unresponsive until the calibration ends.\n\n"
"\tA MESSAGEBOX WILL BE SHOWN ONCE THE CALIBRATION IS COMPLETE.\n");
startTimer();
// Create a whole load of FFTw Plans (wisdom accumulates automatically)
for (int i = 8; i <= 4194304; i *= 2)
{
// Create new buffers and fill
DSP::cFFTin = new fftw_complex[i];
DSP::cFFTout = new fftw_complex[i];
DSP::fconv_FULL_Real_FFT_rdat = new double[i];
DSP::fconv_FULL_Real_FFT_cdat = new fftw_complex[(i/2)+1];
for(int j = 0; j < i; j++)
{
DSP::fconv_FULL_Real_FFT_rdat[j] = j;
DSP::cFFTin[j][0] = j;
DSP::cFFTin[j][1] = j;
DSP::cFFTout[j][0] = 0.0;
DSP::cFFTout[j][1] = 0.0;
}
// Create a plan for complex FFT.
// Use the measure flag to get the best possible FFT for this size
// FFTw "remembers" which FFTs were the fastest during this test.
// at the end of the test, the results are saved to disk and re-used
// upon every initialisation of the DSP Library
DSP::pCF = fftw_plan_dft_1d
(i, DSP::cFFTin, DSP::cFFTout, FFTW_FORWARD, FFTW_MEASURE);
// Destroy the plan
fftw_destroy_plan(DSP::pCF);
// Create a plan for real forward FFT
DSP::pCF = fftw_plan_dft_r2c_1d
(i, fconv_FULL_Real_FFT_rdat, fconv_FULL_Real_FFT_cdat, FFTW_MEASURE);
// Destroy the plan
fftw_destroy_plan(DSP::pCF);
// Create a plan for real inverse FFT
DSP::pCF = fftw_plan_dft_c2r_1d
(i, fconv_FULL_Real_FFT_cdat, fconv_FULL_Real_FFT_rdat, FFTW_MEASURE);
// Destroy the plan
fftw_destroy_plan(DSP::pCF);
// Destroy the buffers. Repeat for each size
delete [] DSP::cFFTin;
delete [] DSP::cFFTout;
delete [] DSP::fconv_FULL_Real_FFT_rdat;
delete [] DSP::fconv_FULL_Real_FFT_cdat;
}
double time = stopTimer();
char * strOutput;
strOutput = (char*) malloc (100);
sprintf(strOutput, "DSP.DLL Calibration complete in %d minutes, %d seconds\n"\
"Please keep a copy of the DSPDLL.ftw file in the root directory of your application\n"\
"to avoid re-calibration in the future\n", (int)time/(int)60, (int)time%(int)60);
AfxMessageBox(strOutput);
isCalibrated = 1;
// Save accumulated wisdom
char * strWisdom = fftw_export_wisdom_to_string();
FILE *fftw_wisdomsave = fopen("DSPDLL.ftw", "w");
fprintf(fftw_wisdomsave, "%s", strWisdom);
fclose(fftw_wisdomsave);
DSP::pCF = NULL;
DSP::cFFTin = NULL;
DSP::cFFTout = NULL;
fconv_FULL_Real_FFT_cdat = NULL;
fconv_FULL_Real_FFT_rdat = NULL;
free(strOutput);
}
}
else
{
// obtain file size.
fseek (fftw_wisdom , 0 , SEEK_END);
long lSize = ftell (fftw_wisdom);
rewind (fftw_wisdom);
// allocate memory to contain the whole file.
char * strWisdom = (char*) malloc (lSize);
// copy the file into the buffer.
fread (strWisdom,1,lSize,fftw_wisdom);
// import the buffer to fftw wisdom
fftw_import_wisdom_from_string(strWisdom);
fclose(fftw_wisdom);
free(strWisdom);
isCalibrated = 1;
return;
}
}
비밀 소스는 특히 특정 FFT의 유형 (실제 복잡한, 1D, 2D) 및 크기에 대한 빠른을 찾기 위해 루틴의 수백을 측정하는 FFTW_MEASURE 플래그를 사용하여 계획을 수립하는 것입니다
DSP::pCF = fftw_plan_dft_1d (i, DSP::cFFTin, DSP::cFFTout,
FFTW_FORWARD, FFTW_MEASURE);
마지막으로 모든 벤치 마크 테스트는 디버거에서 최적화 및 디버거에서 분리 된 릴리스 모드로 컴파일 된 코드에서 호출 된 실행 외의 단일 FFT 계획 단계에서도 수행해야합니다.벤치 마크는 수천 (또는 수백만)의 반복을 반복하여 수행해야하며 평균 실행 시간을 사용하여 결과를 계산해야합니다. 계획 단계에는 많은 시간이 필요하며 실행 계획은 단일 계획으로 여러 번 수행되도록 설계되었습니다.
fftw 라이브러리가 동일한 컴파일러 (및 버전)로 컴파일되어 있습니까? 그들은 같은 깃발로 컴파일되어 있습니까? 동일한 아키텍처 용으로 컴파일 되었습니까? 아마도 Windows 빌드가 CPU 기능을 더 잘 사용하고있을 것입니다. 어쩌면 다른 컴파일러 일 수도 있으므로 다르게 최적화됩니다. –
두 플랫폼에서 사용한 컴파일러의 세부 정보와 코드 및 라이브러리 구축에 사용되는 컴파일 옵션을 게시하십시오. – Mat
은 비트율이 동일합니다 (32 비트 대 64 비트)? 동일한 양의 RAM을 사용할 수 있습니까? 어떤 다른 프로세스가 병렬로 실행되고 있습니까? 모든 가상화가 활성화 되었습니까? – Yahia