openlang

핫 루프에서 try vs catch unreachable, 숫자가 이해가 안 돼요

ts,level,bytes 형식으로 생성한 약 200만 줄에 대해 try parseLine(line)과 parseLine(line) catch unreachable의 시간을 재고 있어요. bytes를 합산하고요. -Doptimize=ReleaseFast로 빌드했어요.

try 쪽은 수백 마이크로초가 나오고, 합계 대신 에러 이름이 출력돼요. catch unreachable 쪽은 수십 ms가 걸리고 합계도 달라요. 두 번째 쪽은 ReleaseSafe와 Debug에서 panic이 나요. "현실적으로 만들려고" 5000줄마다 깨진 줄을 하나씩 넣었어요. --bad-every 0이면 좀 정상으로 보이는데, 왜 이렇게까지 차이가 나는지 모르겠어요.

두 루프는 이래요:

const e = try parse.parseLine(line);
total += e.bytes;
// vs
const e = parse.parseLine(line) catch unreachable;
total += e.bytes;

제 추측은 error return trace나 인라이닝이었어요. 어셈블리는 아직 안 봤어요. 입력 생성은 이미 타이머 밖에 있어요. (splitScalar가 0.12 즈음에 나온 것 같은데, 틀렸으면 무시하세요.)

그래서 이게 실제로 뭘 측정하는 걸까요? 조언 주시면 감사하겠어요.

영어에서 번역원문 보기

이어지는 대화 2

서로의 근거를 따라
  1. 고유 링크

    같은 작업을 처리하는 두 가지 방법을 비교하고 있는 게 아니에요. try 쪽은 첫 번째 깨진 줄에서 빠져나와 버려요. 200만 줄에 몇백 µs면 거의 시작도 못 했다는 뜻이고, 보이는 에러 이름은 그 이른 return에서 나온 거예요. 생성기가 i % 5000 == 0으로 되어 있다면 0번 줄부터 이미 깨져 있어서 바로 죽어요.

    catch unreachable 쪽은 다른 문제예요. ReleaseFast에서는 첫 번째 깨진 줄에서 undefined behaviour라서 옵티마이저가 뭐든 마음대로 할 수 있어요. 그래서 총합이 이상한 거고요. Debug랑 ReleaseSafe는 실제로 검사를 하니까 panic이 나요. 수십 ms도 믿을 수 있는 숫자가 아니에요. 컴파일러가 루프를 이상한 형태로 접어 버렸을 수 있거든요.

    먼저 깨진 줄 0개로 벤치를 돌리고, 그다음에 깨진 줄을 catch continue나 카운터로 처리해서 비교해 보세요. 총합과 함께 실제로 파싱된 줄 수도 출력해서 루프가 끝까지 돌았는지 확인하고요.

    솔직히 저는 codegen 쪽 버그 같아서 Zig 버전도 확인해 볼 것 같아요. 어떤 빌드를 쓰고 있어요?

    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. 단순한 루프가 너무 느려요, gfortran, 200000 x 64 배열

    작은 보정 도구인데 코드는 아래에 있어요. 출력은 맞는데 너무 느려요. detrend+clip은 몇 초씩 걸리고, rms도 원래보다 느려요. 요소당 곱셈 한 번, 덧셈 한 번뿐인데도요. -O3랑 -march=native를 써…

    답글 2최근 활동 fortran
  2. running_mean이 느려요, 시간이 산술 연산이 아니라 memmove에 쓰여요

    센서 데이터를 평활화하고 있어요. 배열은 readings(nstation, ntime)이고, station이 먼저예요. 데이터 파일이 그렇게 배치돼 있고 다른 도구들도 읽기 때문이에요. station에 대해 루프를 한 번 돌…

    답글 1최근 활동 fortran
  3. 어느 빌드 시간을 말하는 건가

    크레이트 분리 이야기는 늘 누군가 빌드 시간 하나를 올리는 것으로 끝난다. 숫자는 두 개고, 움직이는 방향도 다르다. 클린 빌드는 빈 target에서 시작하는 전체 빌드다. 크레이트를 나누면 이쪽은 오히려 조금 나빠질 수 있…

    답글 2최근 활동 rust