Sou um novato em aceleração de GPU. Apenas tentei uma ligação LWJGL básica em CUDA com um kernel simples, sem memória compartilhada, a assinatura da função é a seguinte
__global__ void compute(
unsigned int n,
unsigned long long int* timeMs,
double* a, double* b, double* c,
double *g_odata)
a função do kernel é basicamente recuperar dados para o id do thread dos arrays acima (timeMs, a, b, c etc.) e fazer algumas contas e colocar o resultado no array g_odata no id do thread apropriado. n sendo o número de threads a serem computados (ele verifica se o ID do thread ultrapassa n, é claro). Não há memória compartilhada ou redução.
Agora aqui está o caso curioso sobre n (tamanho total do thread/paralelismo) e tamanho do bloco quando meço o tempo TOTAL necessário para o kernel ser concluído (tenho uma GPU com 80 multiprocessadores)
Por meio disso clock64()
, adicionei carimbo de data / hora na função do kernel antes e depois e coletei o tempo total de cada thread, e é aparente que quanto mais threads houver, mais lentos eles demoram para a MESMA tarefa
Agora perguntas:
- Por que o tempo total diminui após cerca de 100 threads? Dados 80 multiprocessadores e mais de 10 mil núcleos cuda, esperaria que esse número fosse maior, então talvez algum problema de configuração?
- Por que a função do kernel está demorando mais para mais threads? a execução é entrelaçada (ou seja, o escalonador pode pausar um deles antes de concluir e executar outro)
- Por que há um comportamento de platô após um aumento de 100 threads? e por que ele decola novamente
- O desempenho variável com base no número do bloco. Eu li que grade/bloco é apenas a perspectiva do desenvolvedor e não tem influência (especialmente para meus threads totalmente segregados sem compartilhamento/redução). Então, por que isso é importante e como escolher o melhor tamanho de bloco?