Atualmente, se p_N for definido como 5, quando um kernel for analisado e gerado, todas as instâncias de p_N serão substituídas por 5.
Seria útil adicionar uma opção de analisador para que os #defines sejam incluídos no código-fonte gerado e as variáveis do compilador como p_N sejam deixadas no código-fonte gerado.
Isso tornará o código gerado muito mais fácil de ler.
Infelizmente, todas as definições precisam ser expandidas para aplicar transformações de código
Os valores #define
podem ser encontrados em dois lugares
> head ~/.occa/cache/c8141715ac4e4272/raw_source.cpp
#define block 256
/* The MIT License (MIT)
*
> cat ~/.occa/cache/c8141715ac4e4272/build.json | jq .kernel.props.defines
{
"block": 256
}
Concordo que é útil fazer isso para extrair os limites de loop reais e imagino que o analisador foi projetado para fazer isso. No entanto, parece improvável que seja impossível preservar as definições no código. Manter o controle de como os valores são calculados evitaria a necessidade de imprimir seus valores numéricos.
É mais difícil do que parece manter o código e transformá-lo
Define pode ser qualquer coisa, mesmo código parcial
#define foo 3 +
for (int i = 0; i < foo 5; ++i) {}
Manter as linhas #define
também pode causar problemas, pois o compilador ainda executará o pré-processador
... e se o Define for apenas uma constante numérica... ?
... e por que precisamos de lógica extra para isso ....?
Este é um exemplo do kernel de saída
extern "C" __global__ void _occa_ellipticPreconCoarsenHex3D_0(const int Nelements,
const double * __restrict__ R,
const double * __restrict__ qf,
double * __restrict__ qc) {
{
int e = 0 + blockIdx.x;
__shared__ double s_qfff[8][8][8];
__shared__ double s_qcff[2][8][8];
__shared__ double s_qccf[2][2][8];
__shared__ double s_qccc[2][2][2];
__shared__ double s_R[2][8];
{
int k = 0 + threadIdx.z;
{
int j = 0 + threadIdx.y;
{
int i = 0 + threadIdx.x;
const int id = i + j * 8 + k * 8 * 8 + e * 512;
s_qfff[k][j][i] = qf[id];
if ((k == 0) && (j < 2)) {
s_R[j][i] = R[j * 8 + i];
}
}
}
}
Os kernels estão perdendo legibilidade na tradução. Todos esses números foram Definidos.
Dando um passo para trás, o motivo da solicitação de recurso foi
tornar o código gerado muito mais fácil de ler
O código gerado é destinado ao compilador, não aos usuários (semelhante às saídas pré-processadas pelo compilador). Se houver um problema de análise, especialmente porque o analisador ainda não está maduro, pode ser útil dar uma olhada. No entanto, esses problemas devem ser resolvidos ao longo do tempo.
Se o objetivo é facilitar a depuração, concordo que devemos adicionar #line
para corresponder ao código-fonte original
Eu concordo que para depurar isso seria um verdadeiro bônus - boa ideia!
Eu deveria ter sido mais claro sobre o raciocínio por trás dessa solicitação: um caso de uso importante que imagino para as novas ferramentas de geração de código no OCCA 1.0 é como um tradutor de OKL para linguagem de encadeamento nativa para aplicativos não-OCCA. Nesse caso, será importante preservar a legibilidade, pois o código CUDA/OpenCL/HIP/OpenMP gerado será separado do código OKL.
Isso soa razoável
Existem alguns recursos que precisarão ser adicionados primeiro
#define
#defines
é muito difícil, pois precisaríamos rastrear onde eles são definidos e quais escopos eles tocam após as transformaçõesparser::getExpression
, substitua constexpr
por seus valoresconst
constexpr
#define
linhas ao topo como de costumeObrigado por contemplar a solicitação de recurso!
Comentários muito úteis
Isso soa razoável
Existem alguns recursos que precisarão ser adicionados primeiro
#define
#defines
é muito difícil, pois precisaríamos rastrear onde eles são definidos e quais escopos eles tocam após as transformaçõesparser::getExpression
, substituaconstexpr
por seus valoresconst
constexpr
#define
linhas ao topo como de costume