openlang

outliers.log의 줄 수가 :outliers 카운터보다 많아요, future 8개

8개의 future에서 시뮬레이션된 조수 측정값 20000개를 하나의 atom에 fold해요. 임계값을 넘는 측정값은 모두 outliers.log에도 append하고요. 요약은 문제없어요. :n은 항상 20000이고, :outliers는 seed가 고정이라 매번 똑같아요. 그런데 로그의 줄 수가 카운터보다 많아요. 지난번 실행에서는 로그가 250줄 정도였고 카운터는 그보다 조금 낮았어요. 어떤 id는 두 번씩 나와요. --workers 1로 하면 둘이 일치해요.

(defn- log-line [& parts]
  (spit (:log-file config)
        (str (str/join " " parts) "\n")
        :append true))

(defn fold-reading [st r]
  (let [lvl (:level r)]
    (when (outlier? r)
      (log-line "outlier" (:id r) (format "%.3f" lvl)))
    (cond-> (-> st
                (update :n inc)
                (update :sum + lvl)
                (update :sumsq + (* lvl lvl)))
      (outlier? r) (update :outliers inc))))

(defn record! [r]
  (swap! stats fold-reading r))

여러 스레드에서 spit :append를 하면 이중으로 쓰는 건가 싶었는데, 그러면 카운터도 틀려야 하잖아요. partition-all 청크도 확인했는데 겹치지 않아요. :n이 딱 20000이니까요. 실행 전에 로그는 매번 지워요. 같은 seed로 다시 돌려도 줄 수가 매번 달라요.

통계는 정확한데 로그만 틀릴 수 있는 이유가 뭘까요? outlier당 정확히 한 줄만 남기고 싶어요.

영어에서 번역원문 보기

이어지는 대화 1

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

    원인은 swap!의 재시도 같아요. future 8개가 atom 하나를 두고 경쟁하면 compare-and-set이 가끔 실패하고, 함수가 새 값으로 다시 실행돼요. 커밋되는 건 성공한 결과뿐이라 카운터는 정확하고요. 그런데 spit은 버려진 시도를 포함해서 매 시도마다 실행돼요. --workers 1에서 일치하는 것도, 중복 개수가 실행마다 달라지는 것도 이걸로 설명되죠? atoms reference에도 함수가 여러 번 호출될 수 있으니 side effect가 없어야 한다고 나와 있어요.

    fold-reading을 pure하게 두고 이렇게 하면 될 것 같아요:

    (defn record! [r]
      (when (outlier? r)
        (log-line "outlier" (:id r) (format "%.3f" (:level r))))
      (swap! stats fold-reading r))

    그러면 각 측정값이 정확히 한 번만 로그에 남지만, 로그 순서는 swap 순서와 일치하지 않겠죠...

    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. context를 취소했는데도 첫 에러 이후 worker goroutine이 계속 살아 있어요 (항상 workers + 2)

    안녕하세요, 작은 Go CLI인 shotcheck를 만들고 있어요. 폴더 안의 모든 PNG가 App Store 슬롯에서 요구하는 정확한 크기인지 확인하는 도구예요. worker 풀(기본 8개)이 jobs에서 이름을 읽어서 검…

    답글 4최근 활동 go
  2. filter를 async로 바꿔도 멈춤 현상은 그대로예요

    ledgerscan으로 400k개 항목을 검색해요. run을 async로 바꾸고 main에서 await했어요. 100 ms 하트비트 Timer가 계속 돌 줄 알았거든요. 그런데 실제로는 틱이 찍히고, searching "re…

    답글 2최근 활동 dart
  3. await for over ReceivePort가 isolate가 다 끝나도 끝나지 않아요

    안녕하세요, 온도 CSV를 요약해 주는 작은 dart 툴을 만들고 있어요. 큰 파일들이 서로 기다리지 않도록 파일마다 isolate를 하나씩 띄워요. WSL에서 이렇게 실행해요: dart run bin/summarize.da…

    답글 2최근 활동 dart