pub struct PrefetchDataLoader<D>where
D: Dataset,{ /* private fields */ }Expand description
マルチワーカー prefetch 版の SamplerDataLoader(イシュー
#2183・親 #2131)。Sampler が返す添字列を worker スレッドへ
分配して並列に Dataset::batch を実行し、バッチ組み立て
(ホスト側コピー・前処理)を学習ステップと重ねる。
§決定性の契約(R2)
Self::iter は呼び出しスレッド上で Sampler::start_epoch を
1 回呼ぶ。添字生成(Sampler::next_batch)はその後も呼び出し
スレッド(consumer)上でのみ、k の昇順に 1 回ずつ行う(モジュール
冒頭「シャッフル契約」と同じ「RNG 消費はこの呼び出しスレッドだけで
完結させる」方式を踏襲——worker はグローバル RNG に一切触れない)。
ただし呼び出しタイミングは PrefetchConfig::prefetch_depth が
定める投入窓ぶんだけ有界 にする(レビュー指摘・イシュー #2183
コメント: 以前は iter() が epoch 全体の添字列を Vec<Vec<usize>>
として一括 eager 確定しており、prefetch_depth が先読み量を抑える
はずの契約に反して大きな epoch でメモリを使い切り得た)。具体的には
PrefetchBatches::spawn(内部実装)が初回投入窓分だけ next_batch
を呼び、以降は PrefetchBatches::advance_after_delivery(内部実装)
が 1 バッチ届くたびに次の 1 個だけを生成してタスク投入する。
生成される k の
順序自体は eager 版と変わらないため(呼ばれるタイミングが分散する
だけ)、RNG 消費順は不変で決定性契約は保たれる。ただしこれは
組み込みの 3 Sampler 実装(SequentialSampler・
RandomSampler・WeightedRandomSampler)が RNG 消費を
start_epoch 内の 1 回に限り、next_batch は確定済み順列
(IndexBatcher)から純粋に切り出すだけ、という前提の下でのみ
成立する。next_batch 側で RNG を消費するカスタム Sampler
実装は、生成タイミングがスケジューリング(学習ステップの進み方)
に依存するため本契約の対象外(transform/collate フックと同じ
制約。次段落)。worker は dataset.batch(&idx) だけを実行し、
結果は呼び出し順 k で並べ直してから yield する(reorder
buffer)。
この結果、任意の (num_workers, prefetch_depth) の組み合わせで、
出力列(Err の位置と内容を含む)は同じ Sampler を使う
SamplerDataLoader と bit 完全一致する。前提は Dataset::batch
が添字だけで決まる純関数であること(TensorDataset とタプル
実装は該当)。
transform/collate フック(HookedDataLoader 相当)の並列化は
対象外(worker 上の transform がグローバル RNG を使うと消費順が
スケジューリングに依存し決定性契約を破るため。
docs/tensor-core-data-prefetch-decision.md §1.2・§6)。
§ライフサイクル
PrefetchBatches は Drop でタスク送信側を閉じ worker の
join を待つ。イテレータを最後まで消費せず break した場合も、
送信側・受信側の drop により worker は send/recv のエラーで
自然に終了する(デッドロックしない。join の結果は捨てるため
worker の panic がここへ波及しない)。
Implementations§
Source§impl<D> PrefetchDataLoader<D>
impl<D> PrefetchDataLoader<D>
Sourcepub fn new(
dataset: D,
sampler: impl Sampler + 'static,
config: PrefetchConfig,
) -> Result<PrefetchDataLoader<D>, DataError>
pub fn new( dataset: D, sampler: impl Sampler + 'static, config: PrefetchConfig, ) -> Result<PrefetchDataLoader<D>, DataError>
dataset.validate() を実行してから構築する([SamplerDataLoader:: new] と同じ契約)。dataset は Arc で保持し worker 間で共有
する。
Sourcepub fn config(&self) -> PrefetchConfig
pub fn config(&self) -> PrefetchConfig
構築時に渡した PrefetchConfig。
Sourcepub fn num_batches(&self) -> Option<usize>
pub fn num_batches(&self) -> Option<usize>
1 epoch あたりのバッチ数(Sampler::num_batches が Some を
返す場合のみ)。
Sourcepub fn iter(&mut self) -> PrefetchBatches<'_, D> ⓘ
pub fn iter(&mut self) -> PrefetchBatches<'_, D> ⓘ
1 epoch 分のイテレータを返す。start_epoch が失敗した場合は
スレッドを起動せず、最初の next() で 1 回だけ Err を返し
以降は None(SamplerBatches の pending_error と同じ
方式)。config.num_workers() == 0 の場合もスレッドを起動せず、
呼び出しスレッド上で逐次に処理する。返り値は self.sampler を
可変借用する(添字生成が呼び出しスレッド限定である決定性契約を
型で強制する。§ 決定性の契約)ため、次の epoch の iter() は
前の epoch のイテレータが drop された後にしか呼べない。
Trait Implementations§
Auto Trait Implementations§
impl<D> !RefUnwindSafe for PrefetchDataLoader<D>
impl<D> !Sync for PrefetchDataLoader<D>
impl<D> !UnwindSafe for PrefetchDataLoader<D>
impl<D> Freeze for PrefetchDataLoader<D>
impl<D> Send for PrefetchDataLoader<D>
impl<D> Unpin for PrefetchDataLoader<D>
impl<D> UnsafeUnpin for PrefetchDataLoader<D>where
Arc<D>: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more