Fragmentação independente de dialeto

O objetivo a longo prazo é tornar o Shardy um componente totalmente independente, capaz de funcionar com qualquer dialeto MLIR. No momento, o Shardy depende diretamente do StableHLO, mas estamos fazendo progressos para melhorar isso com várias abstrações e interfaces para tornar o Shardy mais flexível.

Regras de fragmentação

Uma regra de fragmentação codifica como propagamos uma operação. Como o Shardy agora depende do StableHLO, ele define regras de fragmentação para cada operação de stablehlo. Além disso, o Shardy fornece o ShardingRuleOpInterface, que pode ser usado pelos proprietários de dialeto nas operações para definir regras de fragmentação para as próprias operações. Enquanto uma operação implementar essa interface, o Shardy poderá se propagar por ela.

def ShardingRuleOpInterface : OpInterface<"ShardingRuleOpInterface"> {
  let methods = [
    InterfaceMethod<
      /*desc=*/[{
        Returns the sharding rule of the op.
      }],
      /*retType=*/"mlir::sdy::OpShardingRuleAttr",
      /*methodName=*/"getShardingRule"
    >,
  ];
}

Operações de fluxo de dados

Algumas operações, como as baseadas em região, exigem uma abordagem diferente, em que as regras de fragmentação, que descrevem apenas a correspondência entre dimensões em todos os operandos e resultados, não são suficientes. Nesses casos, o Shardy define um ShardableDataFlowOpInterface para que os proprietários de dialeto possam descrever a propagação do sharding nas operações. Essa interface fornece métodos para receber as origens e os destinos de cada borda de fluxo de dados pelo proprietário e também para receber e definir os shardings dos proprietários de borda.

def ShardableDataFlowOpInterface :
    OpInterface<"ShardableDataFlowOpInterface"> {
  (get|set)BlockArgumentEdgeOwnerShardings;
  (get|set)OpResultEdgeOwnerShardings;
  getBlockArgumentEdgeOwners;
  getOpResultEdgeOwners;
  getEdgeSources;
  // ...
}

Consulte também Operações de fluxo de dados para ter uma visão geral de alto nível de como processamos as operações de fluxo de dados.

Interfaces ainda não implementadas

No futuro, mais interfaces e características serão adicionadas para tornar o Shardy mais flexível e independente do dialeto. Confira a lista abaixo.

Divisão constante

A maioria dos programas de tensor no MLIR tem uma instância de uma constante que é reutilizada por qualquer operação que precise desse valor. Isso faz sentido quando a constante necessária é a mesma. No entanto, para o particionamento ideal de um programa, gostaríamos de permitir que cada uso de uma constante tenha o próprio particionamento e não seja afetado pela forma como outras operações usam essa constante.

Por exemplo, na figura abaixo, se o add for dividido em fragmentos, isso não afetará como o divide e o subtract (em diferentes partes da computação) são divididos em fragmentos.

Divisão constante

Chamamos isso de dependência falsa: como as constantes são baratas, não há uma dependência real entre as operações que usam a mesma constante. Assim, os usuários podem decidir sobre o sharding das operações constantes (e semelhantes a constantes). Cada uso dessa constante pode ter um sharding diferente que pode se propagar de forma isolada para a própria cópia da subcomputação constante.

Para isso, os usuários do Shardy precisam definir: - Um passe your_dialect.constant -> sdy.constant. - Uma característica sdy::ConstantLike, como iota. - Uma característica mlir::Elementwise para operações element-wise, como add e multiply. - Um sdy::ConstantFoldable para operações como slice/broadcast. Tecnicamente, essas operações podem ser calculadas no momento da compilação, se todos os operandos/resultados forem constantes.

Prioridades de operação

No GSPMD, as operações element-wise são propagadas primeiro, seguidas por operações como matmul. No Shardy, queremos permitir que os usuários definam as próprias prioridades de operação, já que não sabemos a priori sobre os dialetos deles. Por isso, vamos pedir que eles transmitam uma lista de operações na ordem em que querem que o Shardy as propague.

A figura abaixo mostra como as prioridades são usadas no GSPMD para propagar operações na ordem correta.

Prioridades de operação. Consulte o documento do GSPMD para saber por que as prioridades de operação são importantes

Consulte o artigo da GSPMD para uma discussão sobre por que as prioridades de operação são importantes.

Ser independente de dialeto

Desde que você implemente as interfaces, os traços e a transmissão anteriores, o Shardy poderá funcionar para seu dialeto. Estamos trabalhando para tornar o Shardy mais flexível e independente do dialeto. Fique de olho nas próximas atualizações.