Resolver problemas de ParallelRunStep
APLICA-SE A:Python SDK azureml v1
Neste artigo, irá aprender a resolver problemas quando obtém erros ao utilizar a classe ParallelRunStep do SDK do Azure Machine Learning.
Para obter sugestões gerais sobre a resolução de problemas de um pipeline, veja Resolução de problemas de pipelines de machine learning.
Testar scripts localmente
O ParallelRunStep é executado como um passo nos pipelines de ML. Poderá querer testar os scripts localmente como um primeiro passo.
Requisitos de script de entrada
O script de entrada de um ParallelRunStep
tem de conter uma run()
função e, opcionalmente, contém uma função init()
:
init()
: utilize esta função para qualquer preparação dispendiosa ou comum para processamento posterior. Por exemplo, utilize-o para carregar o modelo para um objeto global. Esta função será chamada apenas uma vez no início do processo.Nota
Se o seu
init
método criar um diretório de saída, especifique esseparents=True
eexist_ok=True
. Oinit
método é chamado a partir de cada processo de trabalho em cada nó em que a tarefa está em execução.run(mini_batch)
: a função será executada para cadamini_batch
instância.mini_batch
:ParallelRunStep
invocará o método run e transmitirá uma lista ou pandasDataFrame
como um argumento para o método. Cada entrada no mini_batch será um caminho de ficheiro se a entrada for umFileDataset
ou um pandasDataFrame
se a entrada for umTabularDataset
.response
: o método run() deve devolver um pandasDataFrame
ou uma matriz. Para append_row output_action, estes elementos devolvidos são acrescentados ao ficheiro de saída comum. Para summary_only, os conteúdos dos elementos são ignorados. Para todas as ações de saída, cada elemento de saída devolvido indica uma execução bem-sucedida do elemento de entrada no mini-lote de entrada. Certifique-se de que estão incluídos dados suficientes no resultado de execução para mapear a entrada para executar o resultado de saída. O resultado da execução será escrito no ficheiro de saída e não é garantido que esteja em ordem, deve utilizar alguma chave na saída para mapeá-la para a entrada.Nota
Espera-se um elemento de saída para um elemento de entrada.
%%writefile digit_identification.py
# Snippets from a sample script.
# Refer to the accompanying digit_identification.py
# (https://github.com/Azure/MachineLearningNotebooks/tree/master/how-to-use-azureml/machine-learning-pipelines/parallel-run)
# for the implementation script.
import os
import numpy as np
import tensorflow as tf
from PIL import Image
from azureml.core import Model
def init():
global g_tf_sess
# Pull down the model from the workspace
model_path = Model.get_model_path("mnist")
# Construct a graph to execute
tf.reset_default_graph()
saver = tf.train.import_meta_graph(os.path.join(model_path, 'mnist-tf.model.meta'))
g_tf_sess = tf.Session()
saver.restore(g_tf_sess, os.path.join(model_path, 'mnist-tf.model'))
def run(mini_batch):
print(f'run method start: {__file__}, run({mini_batch})')
resultList = []
in_tensor = g_tf_sess.graph.get_tensor_by_name("network/X:0")
output = g_tf_sess.graph.get_tensor_by_name("network/output/MatMul:0")
for image in mini_batch:
# Prepare each image
data = Image.open(image)
np_im = np.array(data).reshape((1, 784))
# Perform inference
inference_result = output.eval(feed_dict={in_tensor: np_im}, session=g_tf_sess)
# Find the best probability, and add it to the result list
best_result = np.argmax(inference_result)
resultList.append("{}: {}".format(os.path.basename(image), best_result))
return resultList
Se tiver outro ficheiro ou pasta no mesmo diretório que o script de inferência, pode referenciar o mesmo ao encontrar o diretório de trabalho atual. Se quiser importar os pacotes, também pode acrescentar a pasta do pacote a sys.path
.
script_dir = os.path.realpath(os.path.join(__file__, '..',))
file_path = os.path.join(script_dir, "<file_name>")
packages_dir = os.path.join(file_path, '<your_package_folder>')
if packages_dir not in sys.path:
sys.path.append(packages_dir)
from <your_package> import <your_class>
Parâmetros para ParallelRunConfig
ParallelRunConfig
é a configuração principal, por ParallelRunStep
exemplo, no pipeline do Azure Machine Learning. Pode utilizá-lo para moldar o script e configurar os parâmetros necessários, incluindo todas as seguintes entradas:
entry_script
: um script de utilizador como um caminho de ficheiro local que será executado em paralelo em vários nós. Sesource_directory
estiver presente, utilize um caminho relativo. Caso contrário, utilize qualquer caminho acessível no computador.mini_batch_size
: o tamanho do mini-lote transmitido para uma únicarun()
chamada. (opcional; o valor predefinido é10
ficheiros paraFileDataset
e1MB
paraTabularDataset
.)- Para
FileDataset
, é o número de ficheiros com um valor mínimo de1
. Pode combinar vários ficheiros num mini-lote. - Para
TabularDataset
, é o tamanho dos dados. Os valores de exemplo são1024
,1024KB
,10MB
e1GB
. O valor recomendado é1MB
. O mini-lote deTabularDataset
nunca irá ultrapassar os limites dos ficheiros. Por exemplo, se tiver .csv ficheiros com vários tamanhos, o ficheiro mais pequeno é de 100 KB e o maior é 10 MB. Se definirmini_batch_size = 1MB
, os ficheiros com um tamanho inferior a 1 MB serão tratados como um mini-lote. Os ficheiros com um tamanho superior a 1 MB serão divididos em vários mini-lotes.Nota
Os TabularDatasets suportados pelo SQL não podem ser particionados. TabularDatasets de um único ficheiro parquet e grupo de linha única não podem ser particionados.
- Para
error_threshold
: o número de falhasTabularDataset
de registo para e falhas de ficheiros paraFileDataset
isso deve ser ignorado durante o processamento. Se a contagem de erros para toda a entrada for superior a este valor, a tarefa será abortada. O limiar de erro destina-se a toda a entrada e não ao mini-lote individual enviado para orun()
método. O intervalo é[-1, int.max]
. A-1
parte indica ignorar todas as falhas durante o processamento.output_action
: Um dos seguintes valores indica como a saída será organizada:summary_only
: o script de utilizador irá armazenar a saída.ParallelRunStep
utilizará o resultado apenas para o cálculo do limiar de erro.append_row
: Para todas as entradas, apenas será criado um ficheiro na pasta de saída para acrescentar todas as saídas separadas por linha.
append_row_file_name
: Para personalizar o nome do ficheiro de saída para append_row output_action (opcional; o valor predefinido éparallel_run_step.txt
).source_directory
: caminhos para pastas que contêm todos os ficheiros a executar no destino de computação (opcional).compute_target
: sóAmlCompute
é suportado.node_count
: o número de nós de computação a utilizar para executar o script de utilizador.process_count_per_node
: o número de processos de trabalho por nó para executar o script de entrada em paralelo. Para um computador GPU, o valor predefinido é 1. Para um computador CPU, o valor predefinido é o número de núcleos por nó. Um processo de trabalho irá chamarrun()
repetidamente ao transmitir o mini lote que obtém. O número total de processos de trabalho na sua tarefa éprocess_count_per_node * node_count
, que decide o número máximo derun()
execuções em paralelo.environment
: a definição de ambiente python. Pode configurá-lo para utilizar um ambiente Python existente ou para configurar um ambiente temporário. A definição também é responsável por definir as dependências de aplicação necessárias (opcional).logging_level
: Verbosidade do registo. Os valores no aumento da verbosidade são:WARNING
,INFO
eDEBUG
. (opcional; o valor predefinido éINFO
)run_invocation_timeout
: orun()
tempo limite da invocação do método em segundos. (opcional; o valor predefinido é60
)run_max_try
: contagem máxima de tentativas derun()
um mini-lote. Umrun()
falha se for emitida uma exceção ou se não for devolvida nada quandorun_invocation_timeout
é atingido (opcional; o valor predefinido é3
).
Pode especificar mini_batch_size
, , process_count_per_node
node_count
, , logging_level
, run_invocation_timeout
e run_max_try
como PipelineParameter
, para que, quando submeter novamente uma execução de pipeline, possa ajustar os valores dos parâmetros. Neste exemplo, vai utilizar PipelineParameter
para mini_batch_size
e Process_count_per_node
e irá alterar estes valores quando voltar a submeter outra execução.
Visibilidade dos dispositivos CUDA
Para destinos de computação equipados com GPUs, a variável CUDA_VISIBLE_DEVICES
de ambiente será definida em processos de trabalho. Em AmlCompute, pode encontrar o número total de dispositivos GPU na variável AZ_BATCHAI_GPU_COUNT_FOUND
de ambiente , que é definido automaticamente. Se quiser que cada processo de trabalho tenha uma GPU dedicada, defina process_count_per_node
igual ao número de dispositivos GPU num computador. Cada processo de trabalho atribuirá um índice exclusivo a CUDA_VISIBLE_DEVICES
. Se um processo de trabalho parar por qualquer motivo, o próximo processo de trabalho iniciado utilizará o índice de GPU lançado.
Se o número total de dispositivos GPU for inferior process_count_per_node
a , os processos de trabalho serão atribuídos ao índice de GPU até que todos tenham sido utilizados.
Dado que o total de dispositivos GPU é 2 e process_count_per_node = 4
, por exemplo, o processo 0 e o processo 1 terão o índice 0 e 1. O processo 2 e 3 não terão uma variável de ambiente. Para uma biblioteca que utilize esta variável de ambiente para atribuição de GPU, o processo 2 e 3 não terá GPUs e não tentará adquirir dispositivos GPU. Se o processo 0 parar, libertará o índice GPU 0. O próximo processo, que é o processo 4, terá o índice GPU 0 atribuído.
Para obter mais informações, veja Sugestão do CUDA Pro: Controlar a Visibilidade da GPU com CUDA_VISIBLE_DEVICES.
Parâmetros para criar o ParallelRunStep
Crie o ParallelRunStep com o script, a configuração do ambiente e os parâmetros. Especifique o destino de computação que já anexou à área de trabalho como o destino da execução do script de inferência. Utilize ParallelRunStep
para criar o passo do pipeline de inferência de lotes, que utiliza todos os seguintes parâmetros:
name
: o nome do passo, com as seguintes restrições de nomenclatura: exclusivo, 3-32 carateres e regex ^[a-z]([-a-z0-9]*[a-z0-9])?$.parallel_run_config
: umParallelRunConfig
objeto, conforme definido anteriormente.inputs
: um ou mais conjuntos de dados do Azure Machine Learning de tipo único a serem particionados para processamento paralelo.side_inputs
: Um ou mais dados de referência ou conjuntos de dados utilizados como entradas laterais sem necessidade de particionar.output
: umOutputFileDatasetConfig
objeto que representa o caminho do diretório no qual os dados de saída serão armazenados.arguments
: uma lista de argumentos transmitidos ao script de utilizador. Utilize unknown_args para os obter no script de entrada (opcional).allow_reuse
: se o passo deve reutilizar os resultados anteriores quando executado com as mesmas definições/entradas. Se este parâmetro forFalse
, será sempre gerada uma nova execução para este passo durante a execução do pipeline. (opcional; o valor predefinido éTrue
.)
from azureml.pipeline.steps import ParallelRunStep
parallelrun_step = ParallelRunStep(
name="predict-digits-mnist",
parallel_run_config=parallel_run_config,
inputs=[input_mnist_ds_consumption],
output=output_dir,
allow_reuse=True
)
Depurar scripts do contexto remoto
A transição da depuração de um script de classificação localmente para a depuração de um script de classificação num pipeline real pode ser um salto difícil. Para obter informações sobre como localizar os seus registos no portal, veja a secção pipelines de machine learning sobre a depuração de scripts a partir de um contexto remoto. As informações nessa secção também se aplicam a um ParallelRunStep.
Por exemplo, o ficheiro 70_driver_log.txt
de registo contém informações do controlador que inicia o código ParallelRunStep.
Devido à natureza distribuída das tarefas ParallelRunStep, existem registos de várias origens diferentes. No entanto, são criados dois ficheiros consolidados que fornecem informações de alto nível:
~/logs/job_progress_overview.txt
: este ficheiro fornece uma informação de alto nível sobre o número de mini-lotes (também conhecidos como tarefas) criados até agora e o número de mini-lotes processados até agora. Neste final, mostra o resultado da tarefa. Se a tarefa falhar, irá mostrar a mensagem de erro e onde iniciar a resolução de problemas.~/logs/sys/master_role.txt
: este ficheiro fornece a vista do nó principal (também conhecido como orquestrador) da tarefa em execução. Inclui a criação de tarefas, a monitorização do progresso, o resultado da execução.
Os registos gerados a partir do script de entrada com o programa auxiliar EntryScript e as instruções de impressão serão encontrados nos seguintes ficheiros:
~/logs/user/entry_script_log/<node_id>/<process_name>.log.txt
: estes ficheiros são os registos escritos a partir de entry_script com o programa auxiliar EntryScript.~/logs/user/stdout/<node_id>/<process_name>.stdout.txt
: estes ficheiros são os registos de stdout (por exemplo, instrução de impressão) de entry_script.~/logs/user/stderr/<node_id>/<process_name>.stderr.txt
: estes ficheiros são os registos do stderr de entry_script.
Para uma compreensão concisa dos erros no script, existe:
~/logs/user/error.txt
: este ficheiro tentará resumir os erros no script.
Para obter mais informações sobre erros no script, existem:
~/logs/user/error/
: contém rastreios de pilha completos de exceções emitidas durante o carregamento e a execução do script de entrada.
Quando precisar de uma compreensão completa de como cada nó executou o script de classificação, veja os registos de processos individuais de cada nó. Os registos de processos podem ser encontrados na sys/node
pasta agrupadas por nós de trabalho:
~/logs/sys/node/<node_id>/<process_name>.txt
: este ficheiro fornece informações detalhadas sobre cada mini-lote à medida que é recolhido ou concluído por um trabalhador. Para cada mini-lote, este ficheiro inclui:- O endereço IP e o PID do processo de trabalho.
- O número total de itens, a contagem de itens processados com êxito e a contagem de itens falhada.
- Hora de início, duração, tempo de processo e tempo de execução do método.
Também pode ver os resultados das verificações periódicas da utilização de recursos para cada nó. Os ficheiros de registo e os ficheiros de configuração estão nesta pasta:
~/logs/perf
: defina--resource_monitor_interval
para alterar o intervalo de verificação em segundos. O intervalo predefinido é600
, que é aproximadamente 10 minutos. Para parar a monitorização, defina o valor como0
. Cada<node_id>
pasta inclui:os/
: informações sobre todos os processos em execução no nó. Uma verificação executa um comando do sistema operativo e guarda o resultado num ficheiro. No Linux, o comando éps
. No Windows, utilizetasklist
.%Y%m%d%H
: o nome da subpasta é a hora a hora.processes_%M
: O ficheiro termina com o minuto da hora de verificação.
node_disk_usage.csv
: Utilização detalhada do disco do nó.node_resource_usage.csv
: Descrição geral da utilização de recursos do nó.processes_resource_usage.csv
: Descrição geral da utilização de recursos de cada processo.
Como devo proceder para registo do meu script de utilizador a partir de um contexto remoto?
ParallelRunStep pode executar vários processos num nó com base em process_count_per_node. Para organizar os registos de cada processo no nó e combinar a instrução de impressão e registo, recomendamos que utilize o logger ParallelRunStep, conforme mostrado abaixo. Obtém um logger do EntryScript e faz com que os registos apareçam na pasta registos/utilizador no portal.
Um script de entrada de exemplo com o logger:
from azureml_user.parallel_run import EntryScript
def init():
"""Init once in a worker process."""
entry_script = EntryScript()
logger = entry_script.logger
logger.info("This will show up in files under logs/user on the Azure portal.")
def run(mini_batch):
"""Call once for a mini batch. Accept and return the list back."""
# This class is in singleton pattern and will return same instance as the one in init()
entry_script = EntryScript()
logger = entry_script.logger
logger.info(f"{__file__}: {mini_batch}.")
...
return mini_batch
Para onde é que a mensagem do Python logging
se afunda?
ParallelRunStep define um processador no logger de raiz, o que afunda a mensagem para logs/user/stdout/<node_id>/processNNN.stdout.txt
.
logging
predefinição para nivelar INFO
. Por predefinição, os níveis abaixo INFO
não serão apresentados, como DEBUG
.
Como posso escrever num ficheiro para aparecer no portal?
Os ficheiros na logs
pasta serão carregados e apresentados no portal.
Pode obter a pasta logs/user/entry_script_log/<node_id>
como abaixo e compor o caminho do ficheiro para escrever:
from pathlib import Path
from azureml_user.parallel_run import EntryScript
def init():
"""Init once in a worker process."""
entry_script = EntryScript()
log_dir = entry_script.log_dir
log_dir = Path(entry_script.log_dir) # logs/user/entry_script_log/<node_id>/.
log_dir.mkdir(parents=True, exist_ok=True) # Create the folder if not existing.
proc_name = entry_script.agent_name # The process name in pattern "processNNN".
fil_path = log_dir / f"{proc_name}_<file_name>" # Avoid conflicting among worker processes with proc_name.
Como lidar com o início de sessão em novos processos?
Pode gerar novos processos no script de entrada com subprocess
o módulo, ligar-se aos respetivos pipes de entrada/saída/erro e obter os respetivos códigos de retorno.
A abordagem recomendada é utilizar a run()
função com capture_output=True
. Os erros serão apresentados em logs/user/error/<node_id>/<process_name>.txt
.
Se quiser utilizar Popen()
o , deve redirecionar stdout/stderr para ficheiros, como:
from pathlib import Path
from subprocess import Popen
from azureml_user.parallel_run import EntryScript
def init():
"""Show how to redirect stdout/stderr to files in logs/user/entry_script_log/<node_id>/."""
entry_script = EntryScript()
proc_name = entry_script.agent_name # The process name in pattern "processNNN".
log_dir = Path(entry_script.log_dir) # logs/user/entry_script_log/<node_id>/.
log_dir.mkdir(parents=True, exist_ok=True) # Create the folder if not existing.
stdout_file = str(log_dir / f"{proc_name}_demo_stdout.txt")
stderr_file = str(log_dir / f"{proc_name}_demo_stderr.txt")
proc = Popen(
["...")],
stdout=open(stdout_file, "w"),
stderr=open(stderr_file, "w"),
# ...
)
Nota
Um processo de trabalho executa o código "sistema" e o código do script de entrada no mesmo processo.
Se não for stdout
ou stderr
especificado, um subprocesso criado com Popen()
no script de entrada herdará a definição do processo de trabalho.
stdout
irá escrever para logs/sys/node/<node_id>/processNNN.stdout.txt
e stderr
para logs/sys/node/<node_id>/processNNN.stderr.txt
.
Como devo proceder para escrever um ficheiro no diretório de saída e, em seguida, vê-lo no portal?
Pode obter o diretório de saída da EntryScript
classe e escrevê-lo. Para ver os ficheiros escritos, na vista De passo Executar no portal do Azure Machine Learning, selecione o separador Saídas + registos . Selecione a ligação Saídas de dados e, em seguida, conclua os passos descritos na caixa de diálogo.
Utilize EntryScript
no script de entrada, como neste exemplo:
from pathlib import Path
from azureml_user.parallel_run import EntryScript
def run(mini_batch):
output_dir = Path(entry_script.output_dir)
(Path(output_dir) / res1).write...
(Path(output_dir) / res2).write...
Como posso transmitir uma entrada lateral, como um ficheiro ou ficheiros que contenham uma tabela de pesquisa, a todos os meus trabalhadores?
O utilizador pode transmitir dados de referência para o script com side_inputs parâmetro de ParalleRunStep. Todos os conjuntos de dados fornecidos como side_inputs serão montados em cada nó de trabalho. O utilizador pode obter a localização da montagem ao transmitir o argumento.
Crie um Conjunto de Dados que contenha os dados de referência, especifique um caminho de montagem local e registe-o na área de trabalho. Transmita-o para o side_inputs
parâmetro do seu ParallelRunStep
. Além disso, pode adicionar o respetivo caminho na arguments
secção para aceder facilmente ao caminho montado.
Nota
Utilize FileDatasets apenas para side_inputs.
local_path = "/tmp/{}".format(str(uuid.uuid4()))
label_config = label_ds.as_named_input("labels_input").as_mount(local_path)
batch_score_step = ParallelRunStep(
name=parallel_step_name,
inputs=[input_images.as_named_input("input_images")],
output=output_dir,
arguments=["--labels_dir", label_config],
side_inputs=[label_config],
parallel_run_config=parallel_run_config,
)
Depois disso, pode aceder ao mesmo no script de inferência (por exemplo, no método init() da seguinte forma:
parser = argparse.ArgumentParser()
parser.add_argument('--labels_dir', dest="labels_dir", required=True)
args, _ = parser.parse_known_args()
labels_path = args.labels_dir
Como utilizar conjuntos de dados de entrada com a autenticação do principal de serviço?
O utilizador pode transmitir conjuntos de dados de entrada com a autenticação do principal de serviço utilizada na área de trabalho. A utilização deste conjunto de dados em ParallelRunStep requer que o conjunto de dados seja registado para que este construa a configuração ParallelRunStep.
service_principal = ServicePrincipalAuthentication(
tenant_id="***",
service_principal_id="***",
service_principal_password="***")
ws = Workspace(
subscription_id="***",
resource_group="***",
workspace_name="***",
auth=service_principal
)
default_blob_store = ws.get_default_datastore() # or Datastore(ws, '***datastore-name***')
ds = Dataset.File.from_files(default_blob_store, '**path***')
registered_ds = ds.register(ws, '***dataset-name***', create_new_version=True)
Como Verificar o Progresso e Analisá-lo
Esta secção é sobre como verificar o progresso de uma tarefa ParallelRunStep e verificar a causa de um comportamento inesperado.
Como verificar o progresso da tarefa?
Além de analisar o estado geral da StepRun, a contagem de mini-lotes agendados/processados e o progresso da geração de saída podem ser visualizados em ~/logs/job_progress_overview.<timestamp>.txt
. O ficheiro roda diariamente, pode verificar o ficheiro com o carimbo de data/hora maior para obter as informações mais recentes.
O que devo verificar se não há progresso durante algum tempo?
Pode aceder ~/logs/sys/errror
para ver se existe alguma exceção. Se não existir nenhum, é provável que o script de entrada esteja a demorar muito tempo, pode imprimir informações de progresso no seu código para localizar a parte demorada ou adicionar "--profiling_module", "cProfile"
ao de ParallelRunStep
para gerar um ficheiro de perfil com o arguments
nome em <process_name>.profile
~/logs/sys/node/<node_id>
pasta.
Quando é que um trabalho vai parar?
se não for cancelada, a tarefa irá parar com o estado:
- Concluído. Se todos os mini-lotes tiverem sido processados e a saída tiver sido gerada para
append_row
o modo. - Falha. Se
error_threshold
a entradaParameters for ParallelRunConfig
for excedida, ou ocorreu um erro de sistema durante a tarefa.
Onde encontrar a causa principal da falha?
Pode seguir a oportunidade potencial ~logs/job_result.txt
para localizar a causa e o registo de erros detalhado.
A falha do nó afetará o resultado da tarefa?
Não se existirem outros nós disponíveis no cluster de computação designado. O orquestrador iniciará um novo nó como substituição e ParallelRunStep é resiliente a essa operação.
O que acontece se init
a função no script de entrada falhar?
ParallelRunStep tem um mecanismo para tentar novamente durante um determinado tempo para dar oportunidade de recuperação de problemas transitórios sem atrasar a falha da tarefa por muito tempo, o mecanismo é o seguinte:
- Se após o início de um nó,
init
em todos os agentes continuar a falhar, deixaremos de tentar após3 * process_count_per_node
falhas. - Se após o início do trabalho,
init
em todos os agentes de todos os nós continuar a falhar, deixaremos de tentar se a tarefa for executada durante mais de 2 minutos e houver2 * node_count * process_count_per_node
falhas. - Se todos os agentes estiverem bloqueados
init
durante mais de3 * run_invocation_timeout + 30
segundos, a tarefa falhará devido a nenhum progresso durante demasiado tempo.
O que vai acontecer no OutOfMemory? Como posso verificar a causa?
ParallelRunStep definirá a tentativa atual de processar o estado de falha do mini-lote e tentará reiniciar o processo falhado. Pode verificar ~logs/perf/<node_id>
se encontra o processo que consome memória.
Por que motivo tenho muitos ficheiros processNNN?
ParallelRunStep iniciará novos processos de trabalho em substituição dos que saíram anormalmente e cada processo irá gerar um processNNN
ficheiro como registo. No entanto, se o processo falhou devido à exceção durante a init
função do script de utilizador e se o erro se repetiu continuamente por 3 * process_count_per_node
vezes, não será iniciado nenhum novo processo de trabalho.
Passos seguintes
Veja estes blocos de notas do Jupyter que demonstram pipelines do Azure Machine Learning
Veja a referência do SDK para obter ajuda com o pacote azureml-pipeline-steps .
Veja a documentação de referência para a classe ParallelRunConfig e documentação para a classe ParallelRunStep.
Siga o tutorial avançado sobre como utilizar pipelines com ParallelRunStep. O tutorial mostra como transmitir outro ficheiro como uma entrada lateral.