매우 큰 (10-100GB) 바이너리 파일의 데이터 스트림을 분석하는 코드가 있습니다. 잘 작동하므로 최적화를 시작할 때가되었으며 현재는 디스크 IO가 가장 큰 병목입니다.디스크 입출력 최적화
두 가지 유형의 파일이 사용 중입니다. 첫 번째 유형의 파일은 물리적으로 의미있는 부동 소수점 값으로 변환하기 위해 I/O 이후에 크기를 조정해야하는 16 비트 정수 스트림으로 구성됩니다. 청크로 파일을 읽었고 한 번에 하나의 16 비트 코드를 읽고 필요한 확장을 수행 한 다음 결과를 배열에 저장하여 데이터 청크를 읽었습니다. 코드는 다음과 같습니다 :
int64_t read_current_chimera(FILE *input, double *current,
int64_t position, int64_t length, chimera *daqsetup)
{
int64_t test;
uint16_t iv;
int64_t i;
int64_t read = 0;
if (fseeko64(input, (off64_t)position * sizeof(uint16_t), SEEK_SET))
{
return 0;
}
for (i = 0; i < length; i++)
{
test = fread(&iv, sizeof(uint16_t), 1, input);
if (test == 1)
{
read++;
current[i] = chimera_gain(iv, daqsetup);
}
else
{
perror("End of file reached");
break;
}
}
return read;
}
chimera_gain 함수는 16 비트 정수를 취하고 크기를 조정하며 저장을 위해 double을 반환합니다.
두 번째 파일 형식에는 64 비트 double이 포함되어 있지만 두 개의 열이 포함되어 있습니다. 그 중 두 번째 열에는 첫 번째 파일 만 필요합니다. 이렇게하려면 두 개의 쌍을 자유롭게 설정하고 두 번째 쌍을 버립니다. 이중은 사용 전에 엔디 언 스왑되어야합니다. 나는이 작업을 수행하는 데 사용하는 코드는 다음과 같습니다 :
는int64_t read_current_double(FILE *input, double *current, int64_t position, int64_t length)
{
int64_t test;
double iv[2];
int64_t i;
int64_t read = 0;
if (fseeko64(input, (off64_t)position * 2 * sizeof(double), SEEK_SET))
{
return 0;
}
for (i = 0; i < length; i++)
{
test = fread(iv, sizeof(double), 2, input);
if (test == 2)
{
read++;
swapByteOrder((int64_t *)&iv[0]);
current[i] = iv[0];
}
else
{
perror("End of file reached: ");
break;
}
}
return read;
}
사람은 빨리 나는 현재 일을하고있는 것보다 크게 될 것이다 이러한 파일 형식을 읽는 방법을 제안 할 수 있습니까?
디스크 I/O의 속도를 높이기 위해 할 수있는 방법은 없습니다. 당신이 할 수있는 유일한 방법은 당신이하는 I/O의 양을 최소화하는 것입니다. 파일에서 많은 부분을 뛰어 넘지 말고 파일의 같은 부분에서 값을 함께 사용하십시오. – Barmar
캐시 사용을 최적화하려면 한 번에 두 개 이상의 값을 읽어야합니다. –
@Barmar 음, 모든 디스크 IO 방법이 동일하지는 않습니다. 예를 들어, fscanf를 사용하는 것은 fread보다 훨씬 느립니다. 어쩌면 fread를 사용하여 한 번에 하나씩이 아닌 많은 양의 데이터를 읽으면 차이가 생길 수 있습니다. 옵션이 아직없는 것 같습니다. HDD의 실제 입출력 작업은 내가 제어 할 수있는 것이 아니라는 것을 알고 있습니다. 그러나 소프트웨어 측면에서 오버 헤드를 줄이는 방법은 거의 확실합니다. – KBriggs