2013-07-27 3 views
0

저는 GPU에서 수치 시뮬레이션을하고 있으며, 주기적으로 .dat 파일에 CSV 데이터를 쓰는 데 많은 시간을 소비하고 있습니다. fprintf()를 사용하는 것보다 .dat 파일에 데이터를 쓰는 더 빠른 방법이 있습니까? CSV 데이터가 필요하기 때문에 fwrite()가 작동하지 않을 것이라고 생각합니다.fprintf()보다 CSV 데이터를 더 빨리 작성할 수 있습니까?

다음은 내 데이터를 참조 용으로 파일에 쓸 때 사용하는 코드입니다.

for(int k = 0;k<gridsize;k++){ 
    for(int j = 0;j<gridsize;j++){ 
     fprintf(tempE, "%f,", h_Estate[j*gridsize + k]); 
    } 
} 
fprintf(tempE,"\n"); 
+0

가 howmuch 데이터는 작성해야합니까? – kangshiyin

+0

격자의 크기에 따라 중첩 for 루프의 부동 소수점 값이 60,000에서 250,000 사이에 있습니다. – user1968603

답변

0

많은 양의 데이터를 텍스트 형식으로 디스크에 기록하는 것은 현명한 선택이 아닙니다. 텍스트 형식은 사람을위한 것이지만 250,000 개의 숫자는 사람의 눈에는 아무런 의미가 없습니다.

EXCEL 또는 Matlab에서 추가 통계를 위해 CSV 형식이 필요하다고 가정합니다. C 코드에서 통계를 작성하고 디스크에 결과를 기록하는 것이 더 좋습니다. 데이터 크기는 작아야합니다. matlab을 사용하면 이진 데이터도 사용할 수 있습니다. 이 경우 수천 개의 fprintf() 대신 하나의 fwrite()를 사용해야합니다.

다른 솔루션은 별도의 프로그램을 사용하여 이진 데이터를 CSV 텍스트 형식으로 다시 포맷하는 것을 포함합니다.

0

기본 OS가 fprintf()를 처리하는 방식에 따라 fwrite()에서 효율성을 얻을 수 있습니다.

앞서 언급 한 것처럼 fwrite()를 직접 수행 할 수는 없지만 sprintf()를 사용하여 csv 텍스트의 서식을 지정한 다음 큰 버퍼로 밀어 넣을 수 있습니다. 버퍼가 가득 차면 전체 버퍼를 fwrite()합니다.

운영 체제 내에서 파일 I/O를 구현하면 이미이 작업이 수행되기 때문에 fprint()가 fprintf()보다 더 효율적이지 않을 수 있습니다.

에릭의 답변에서 언급했듯이이 데이터를 저장하는 가장 효율적인 방법은 직접 바이너리 형식을 사용하는 것입니다. 예를 들어, 데이터를 완전 부동 소수점 정밀도가 필요합니까? 예를 들어, 데이터를 완전 부동 소수점 정밀도가 필요합니까? 보고하는 계산을위한 적절한 정밀도를 유지하면서 16 비트 고정 소수점 int로 변환하고 32 비트 부호없는 int 당 두 개의 데이터 포인트를 저장할 수 있습니까? 부호있는 int 집합으로 취급하면 16 비트 부호있는 int 값은 5 자리 정밀도가됩니다.

이 데이터에 대해 추가 처리를 수행하는 경우 처리 시간이 제어 할 수 없으므로 Excel 또는 Matlab을 사용하지 않으려 고합니다. C 또는 C++로 처리 알고리즘을 개발하면 이진 데이터 형식이 문제가되지 않습니다.

이 데이터를 그래프로 표시하는 경우 그래픽 디스플레이는 데이터를 기본적으로 다운 샘플링합니다. 따라서 10k 포인트와 비슷한 것으로 처리하고 플롯에 의미있는 출력 통계를 출력 할 수 있습니다.

어쨌든, 내 아이디어가 있습니다. 아마 당신이 이미 문제를 풀었 기 때문에 좀 더 일반적인 의미로 작성되었으므로 아마도 비슷한 질문을 한 다른 사람들이 읽게 될 것입니다.

편집 : 여기

// what's faster, fwrite or fprintf? 

#include <stdio.h> 
#include <stdlib.h> 

#include <windows.h> 

#define HUGE_NUMBER 1000 

LARGE_INTEGER ticksPerSecond; 
LARGE_INTEGER time1; 
LARGE_INTEGER time2; 

float floatDiffTime; 
const int runs = 1000000; 

int main(int argc, char* argv[]) 
{ 
    // Get the speed of the CPU 
    QueryPerformanceFrequency(&ticksPerSecond); 
    printf("Your computer does %lld ticks per second\n", ticksPerSecond.QuadPart); 
    // %lld means type "long long" int, which is the 
    // 64 bit int which is what we want here. 

    // define some random valued variables to use 
    // in the print statements 
    int a = 5; 
    double b = 9.2919e92; 
    char c = 'x'; 
    char * d = "blah blah blah"; 

    // test start: open a file to write 
    FILE *outfile = fopen("testfile.txt", "w"); 

    char buf[HUGE_NUMBER]; 
    int i; 
    int index = 0; 

    //Test line-by-line fprintf 
    // START timing 
    QueryPerformanceCounter(&time1); 
    memset(buf,'\0', HUGE_NUMBER); 
    for(i=0; i<runs; i++) 
    { 
     fprintf(outfile, "blah %i %f %c %s\n", a, b, c, d); 
    } 
    fflush (outfile); 
    fclose(outfile); 

    // STOP timing 
    QueryPerformanceCounter(&time2); 

    // get the difference between time1 and time2, 
    // and that is how long the for loop took to run. 
    floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; 
    printf("line-by-line fprintf took %f seconds\n", floatDiffTime); 

    //Test fprintf 
    // START timing 
    QueryPerformanceCounter(&time1); 
    memset(buf,'\0', HUGE_NUMBER); 
    for(i=0; i<runs; i++) 
    { 
     sprintf(&buf[index], "blah %i %f %c %s\n", a, b, c, d); 
     index += strlen(&buf[index]); 
     if(index >= HUGE_NUMBER) { 
      fprintf(outfile, "%s", buf); 
      index = 0; 
      memset(buf,'\0', HUGE_NUMBER); 
     } 
    } 
    fflush (outfile); 
    fclose(outfile); 

    // STOP timing 
    QueryPerformanceCounter(&time2); 

    // get the difference between time1 and time2, 
    // and that is how long the for loop took to run. 
    floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; 
    printf("fprintf took %f seconds\n", floatDiffTime); 

    //Test fwrite 
    outfile = fopen("testfile.txt", "w"); 
    index = 0; 
    ///////////////////// 
    // START timing 
    QueryPerformanceCounter(&time1); 
    memset(buf,'\0', HUGE_NUMBER); 
    for(i=0; i<runs; i++) 
    { 
     sprintf(&buf[index], "blah %i %f %c %s\n", a, b, c, d); 
     index += strlen(&buf[index]); 
     if(index >= HUGE_NUMBER) { 
      fwrite(buf, 1, strlen(buf), outfile); 
      index = 0; 
      //printf("buf size: %d\n", strlen(buf)); 
      memset(buf,'\0', HUGE_NUMBER); 
     } 
    } 

    fflush(outfile); 
    fclose(outfile); 
    //////////////////// 
    // STOP timing 
    QueryPerformanceCounter(&time2); 

    // get the difference between time1 and time2, 
    // and that is how long the for loop took to run. 
    floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; 
    printf("fwrite took %f seconds\n", floatDiffTime); 

    //Test WriteFile 
    outfile = fopen("testfile.txt", "w"); 
    index = 0; 
    DWORD bWritten = 0; 
    ///////////////////// 
    // START timing 
    QueryPerformanceCounter(&time1); 
    memset(buf,'\0', HUGE_NUMBER); 
    for(i=0; i<runs; i++) 
    { 
     sprintf(&buf[index], "blah %i %f %c %s\n", a, b, c, d); 
     index += strlen(&buf[index]); 
     if(index >= HUGE_NUMBER) { 
      WriteFile(outfile, buf, strlen(buf), &bWritten, NULL); 
      index = 0; 
      //printf("buf size: %d\n", strlen(buf)); 
      memset(buf,'\0', HUGE_NUMBER); 
     } 
    } 

    fflush(outfile); 
    fclose(outfile); 
    //////////////////// 
    // STOP timing 
    QueryPerformanceCounter(&time2); 

    // get the difference between time1 and time2, 
    // and that is how long the for loop took to run. 
    floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; 
    printf("WriteFile took %f seconds\n", floatDiffTime); 


    //Test WriteFile 
    outfile = fopen("testfile.txt", "w"); 
    index = 0; 
    bWritten = 0; 
    ///////////////////// 
    // START timing 
    QueryPerformanceCounter(&time1); 
    memset(buf,'\0', HUGE_NUMBER); 
    for(i=0; i<runs; i++) 
    { 
     sprintf(&buf[index], "blah %i %f %c %s\n", a, b, c, d); 
     WriteFile(outfile, buf, strlen(buf), &bWritten, NULL); 
     memset(buf,'\0', strlen(buf)); 
    } 

    fflush(outfile); 
    fclose(outfile); 
    //////////////////// 
    // STOP timing 
    QueryPerformanceCounter(&time2); 

    // get the difference between time1 and time2, 
    // and that is how long the for loop took to run. 
    floatDiffTime = ((float)time2.QuadPart - time1.QuadPart)/ticksPerSecond.QuadPart; 
    printf("WriteFile line-by-line took %f seconds\n", floatDiffTime); 


    return 0;  
} 

그리고 결과 아래 내가 달릴 흥미 검사, 완전한 컴파일 가능한 소스는 ???

Your computer does 2337929 ticks per second 
line-by-line fprintf took 2.970491 seconds 
fprintf took 2.345687 seconds 
fwrite took 3.456101 seconds 
WriteFile took 2.131118 seconds 
WriteFile line-by-line took 2.495092 seconds 

그런 다음 fprintf와로 발송 문자열로 많은 양의 데이터를 버퍼링과 같다() (휴대용) 또는 Windows의 WriteFile() 호출이 처리하는 가장 효율적인 방법이 있습니다 (사용하여 Windows 경우).

컴파일러 명령 :

gcc write_speed_test.c -o wspt 

컴파일러 버전 :

$ gcc -v 
Using built-in specs. 
Target: i686-w64-mingw32 
Configured with: ../gcc44-svn/configure --target=i686-w64-mingw32 --host=i686-w64-mingw32 --disable-multilib --disable-nls --disable-win32-registry --prefix=/mingw32 --with-gmp=/mingw32 --with-mpfr=/mingw32 --enable-languages=c,c++ 
Thread model: win32 
gcc version 4.4.3 (GCC) 
관련 문제