將數據集處理移動到 tf.data 服務的轉換。
用法
tf.data.experimental.service.distribute(
processing_mode, service, job_name=None, consumer_index=None,
num_consumers=None, max_outstanding_requests=None, data_transfer_protocol=None,
compression='AUTO', target_workers='AUTO'
)
參數
-
processing_mode
tf.data.experimental.service.ShardingPolicy
指定如何在 tf.data 工作人員之間分片數據集。有關詳細信息,請參閱tf.data.experimental.service.ShardingPolicy
。為了向後兼容,processing_mode
也可以設置為字符串"parallel_epochs"
或"distributed_epoch"
,它們分別等效於ShardingPolicy.OFF
和ShardingPolicy.DYNAMIC
。 -
service
指示如何連接到 tf.data 服務的字符串或元組。如果它是一個字符串,它應該采用[<protocol>://]<address>
格式,其中<address>
標識調度程序地址,並且可以選擇使用<protocol>
來覆蓋要使用的默認協議。如果它是一個元組,它應該是(協議,地址)。 -
job_name
(可選。)作業的名稱。如果提供,它必須是一個非空字符串。這個論點使得多個數據集共享同一個作業成為可能。默認行為是數據集創建匿名的專有作業。 -
consumer_index
(可選。)從0
到num_consumers
範圍內的消費者索引。必須與num_consumers
一起指定。指定後,消費者將以嚴格的 round-robin 順序從作業中讀取,而不是默認的 first-come-first-served 順序。 -
num_consumers
(可選。)將從作業中消費的消費者數量。必須與consumer_index
一起指定。指定後,消費者將以嚴格的 round-robin 順序從作業中讀取,而不是默認的 first-come-first-served 順序。當指定num_consumers
時,數據集必須具有無限基數,以防止生產者提前耗盡數據並導致消費者不同步。 -
max_outstanding_requests
(可選。)可以同時請求多少元素的限製。您可以使用此選項來控製使用的內存量,因為distribute
不會使用超過element_size
*max_outstanding_requests
的內存。 -
data_transfer_protocol
(可選。)用於通過 tf.data 服務傳輸數據的協議。默認情況下,使用 gRPC 傳輸數據。 -
compression
如何在通過網絡傳輸數據集元素之前對其進行壓縮。 "AUTO" 將如何壓縮的決定留給 tf.data 服務運行時。None
表示不壓縮。 -
target_workers
(可選。)從哪些工人那裏讀取。如果"AUTO"
, tf.data 運行時決定從哪些工作人員讀取。如果"ANY"
,從任何 tf.data 服務工作者讀取。如果"LOCAL"
,僅從本地 in-processs tf.data 服務人員讀取。"AUTO"
適用於大多數情況,而用戶可以指定其他目標。例如,"LOCAL"
有助於避免 RPC 和數據複製,如果每個 TF 工作人員與 tf.data 服務工作人員位於同一位置。共享作業的使用者必須使用相同的target_workers
。默認為"AUTO"
。
返回
-
Dataset
數據服務生成的元素的Dataset
。
當您迭代包含 distribute
轉換的數據集時,tf.data 服務會創建一個 "job",它會為數據集迭代生成數據。
tf.data 服務使用一組工作人員來準備數據以訓練您的模型。 tf.data.experimental.service.distribute
的 processing_mode
參數說明了如何利用多個工作人員來處理輸入數據集。目前有兩種處理模式可供選擇:"distributed_epoch"和"parallel_epochs"。
"distributed_epoch" 表示數據集將被拆分到所有 tf.data 服務工作者中。調度程序為數據集生成"splits",並將它們發送給工作人員進行進一步處理。例如,如果數據集以文件名列表開頭,則調度程序將遍曆文件名並將文件名發送給 tf.data 工作人員,後者將對這些文件執行其餘的數據集轉換。 "distributed_epoch" 當您的模型需要僅查看數據集的每個元素一次,或者需要按 generally-sequential 順序查看數據時很有用。 "distributed_epoch" 僅適用於具有可拆分源的數據集,例如 Dataset.from_tensor_slices
、 Dataset.list_files
或 Dataset.range
。
"parallel_epochs" 表示整個輸入數據集將由每個 tf.data 服務工作者獨立處理。出於這個原因,重要的是非確定性地打亂數據(例如文件名),以便每個工作人員以不同的順序處理數據集的元素。 "parallel_epochs" 可用於分發不可拆分的數據集。
如果有兩個工作人員,"parallel_epochs" 將生成數據集的每個元素兩次:
dispatcher = tf.data.experimental.service.DispatchServer()
dispatcher_address = dispatcher.target.split("://")[1]
# Start two workers
workers = [
tf.data.experimental.service.WorkerServer(
tf.data.experimental.service.WorkerConfig(
dispatcher_address=dispatcher_address)) for _ in range(2)
]
dataset = tf.data.Dataset.range(10)
dataset = dataset.apply(tf.data.experimental.service.distribute(
processing_mode="parallel_epochs", service=dispatcher.target))
print(sorted(list(dataset.as_numpy_iterator())))
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9]
另一方麵,"distributed_epoch" 仍然會生成每個元素一次:
dispatcher = tf.data.experimental.service.DispatchServer()
dispatcher_address = dispatcher.target.split("://")[1]
workers = [
tf.data.experimental.service.WorkerServer(
tf.data.experimental.service.WorkerConfig(
dispatcher_address=dispatcher_address)) for _ in range(2)
]
dataset = tf.data.Dataset.range(10)
dataset = dataset.apply(tf.data.experimental.service.distribute(
processing_mode="distributed_epoch", service=dispatcher.target))
print(sorted(list(dataset.as_numpy_iterator())))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
使用 apply(tf.data.experimental.service.distribute(...))
時,apply
轉換之前的數據集在 tf.data 服務中執行,而 apply
之後的操作發生在本地進程中。
dispatcher = tf.data.experimental.service.DispatchServer()
dispatcher_address = dispatcher.target.split("://")[1]
workers = [
tf.data.experimental.service.WorkerServer(
tf.data.experimental.service.WorkerConfig(
dispatcher_address=dispatcher_address)) for _ in range(2)
]
dataset = tf.data.Dataset.range(5)
dataset = dataset.map(lambda x:x*x)
dataset = dataset.apply(
tf.data.experimental.service.distribute("parallel_epochs",
dispatcher.target))
dataset = dataset.map(lambda x:x+1)
print(sorted(list(dataset.as_numpy_iterator())))
[1, 1, 2, 2, 5, 5, 10, 10, 17, 17]
在上麵的示例中,數據集操作(在對元素應用distribute
函數之前)將在 tf.data 工作人員上執行,並且通過 RPC 提供元素。剩餘的轉換(在調用 distribute
之後)將在本地執行。調度程序和工作人員將綁定到使用的空閑端口(隨機選擇),以便相互通信。但是,要將它們綁定到特定端口,可以傳遞 port
參數。
job_name
參數允許在多個數據集之間共享作業。不是每個數據集都創建自己的作業,而是所有具有相同 job_name
的數據集將從同一個作業中使用。將為數據集的每次迭代創建一個新作業(每次重複 Dataset.repeat
計為一次新迭代)。假設 DispatchServer
在 localhost:5000
上提供服務,並且兩個訓練工作者(在單個客戶端或 multi-client 設置中)迭代以下數據集,並且有一個 tf.data 工作者:
range5_dataset = tf.data.Dataset.range(5)
dataset = range5_dataset.apply(tf.data.experimental.service.distribute(
"parallel_epochs", "localhost:5000", job_name="my_job_name"))
for iteration in range(3):
print(list(dataset))
每個作業的元素將在兩個進程之間拆分,進程在 first-come first-served 的基礎上使用元素。一種可能的結果是進程 1 打印
[0, 2, 4]
[0, 1, 3]
[1]
並處理 2 個打印件
[1, 3]
[2, 4]
[0, 2, 3, 4]
在 tf.data 服務的生命周期內,不得在不同的訓練作業中重複使用作業名稱。一般來說,tf.data 服務預計會在單個訓練作業的持續時間內存在。要將 tf.data 服務用於多個訓練作業,請確保使用不同的作業名稱以避免衝突。例如,假設訓練作業使用 job_name="job"
調用 distribute
並讀取直到輸入結束。如果另一個獨立作業連接到同一個 tf.data 服務並嘗試從 job_name="job"
讀取,它將立即接收輸入結束,而不會獲取任何數據。
協調數據讀取
默認情況下,當多個消費者從同一個作業中讀取數據時,他們會在 first-come first-served 的基礎上接收數據。在某些用例中,協調消費者是有利的。在每一步,消費者都從同一個工作人員那裏讀取數據。
例如,tf.data 服務可用於在同步訓練期間跨集群協調示例大小,以便在每個步驟中,所有副本都在 similar-sized 元素上進行訓練。為此,請定義一個數據集,該數據集生成幾輪 num_consumers
連續 similar-sized 批次,然後通過設置 consumer_index
和 num_consumers
啟用協調讀取。
注意:為了讓消費者保持同步,循環數據消費要求數據集具有無限的基數。您可以通過在數據集定義的末尾添加 .repeat()
來獲得此信息。
Keras 和分發策略
distribute
轉換生成的數據集可以像任何其他 tf.data.Dataset
一樣傳遞到 Keras 的 Model.fit
或 Distribution Strategy 的 tf.distribute.Strategy.experimental_distribute_dataset
。我們建議在調用 distribute
時設置 job_name
,這樣如果有多個工作人員,他們就可以從同一個作業中讀取數據。請注意,在設置 job_name
時,通常由 experimental_distribute_dataset
執行的自動分片將被禁用,因為共享作業已經導致在工作人員之間拆分數據。當使用共享作業時,數據將在工作人員之間動態平衡,以便他們大約在同一時間到達輸入結束。與自動分片相比,這會導致更好的工作人員利用率,其中每個工作人員處理一組獨立的文件,並且一些工作人員可能比其他工作人員更早地用完數據。
相關用法
- Python tf.data.experimental.service.DispatchServer用法及代碼示例
- Python tf.data.experimental.service.from_dataset_id用法及代碼示例
- Python tf.data.experimental.service.DispatchServer.start用法及代碼示例
- Python tf.data.experimental.service.DispatchServer.join用法及代碼示例
- Python tf.data.experimental.service.WorkerServer.join用法及代碼示例
- Python tf.data.experimental.service.WorkerServer用法及代碼示例
- Python tf.data.experimental.service.register_dataset用法及代碼示例
- Python tf.data.experimental.save用法及代碼示例
- Python tf.data.experimental.snapshot用法及代碼示例
- Python tf.data.experimental.shuffle_and_repeat用法及代碼示例
- Python tf.data.experimental.sample_from_datasets用法及代碼示例
- Python tf.data.experimental.RandomDataset.group_by_window用法及代碼示例
- Python tf.data.experimental.SqlDataset.enumerate用法及代碼示例
- Python tf.data.experimental.make_saveable_from_iterator用法及代碼示例
- Python tf.data.experimental.SqlDataset.zip用法及代碼示例
- Python tf.data.experimental.Counter用法及代碼示例
- Python tf.data.experimental.SqlDataset.shard用法及代碼示例
- Python tf.data.experimental.CsvDataset.window用法及代碼示例
- Python tf.data.experimental.RandomDataset.cache用法及代碼示例
- Python tf.data.experimental.SqlDataset.snapshot用法及代碼示例
注:本文由純淨天空篩選整理自tensorflow.org大神的英文原創作品 tf.data.experimental.service.distribute。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。