Visão Geral do Operador aclRfft1D
O operador aclRfft1D realiza a Transformada de Fourier Rápida para sinais reais (RFFT) em um tensor de entrada. Diferente da FFT padrão, a RFFT aproveita a simetria hermitiana de sinais reais para fornecer apenas as frequências positivas, resultando em uma computação mais eficiente.
Suporte de Hardware
| Plataforma | Suporte |
|---|---|
| Ascend 950PR / Ascend 950DT | Não |
| Produtos de Treinamento/Inferência Atlas A3 | Sim |
| Produtos de Treinamento/Inferência Atlas A2 | Sim |
| Produtos de Inferência Atlas 200I/500 A2 | Não |
| Série de Inferência Atlas (Geral) | Não |
| Série de Treinamento Atlas (Geral) | Não |
Definição Matemática
A transformação segue a fórmula clássica da DFT aplicada a uma sequência de entrada real:
$$ X_{k} = \sum_{n=0}^{N-1} x_{n} \cdot e^{-i2\pi \frac{k}{N}n} $$
Para uma entrada real $x$, a saída $X_k$ contém apenas os componentes de frequência não negativos, economizando espaço de memória.
Protótipos das Funções
A execução do operador é dividida em duas etapas: cálculo do espaço de trabalho (workspace) e a execução propriamente dita.
aclnnStatus aclRfft1DGetWorkspaceSize(
const aclTensor* input,
int64_t signalLength,
int64_t dimension,
int64_t normalization,
aclTensor* output,
uint64_t* workspaceSize,
aclOpExecutor** opExecutor);
aclnnStatus aclRfft1D(
void* workspace,
uint64_t workspaceSize,
aclOpExecutor* opExecutor,
aclrtStream rtStream);
Descrição de Parâmetros
aclRfft1DGetWorkspaceSize
| Parâmetro | Tipo | Direção | Descrição |
|---|---|---|---|
| input | aclTensor* | Entrada | Tensor de entrada real (FLOAT). Suporta 1 a 7 dimensões. |
| signalLength | int64_t | Entrada | Comprimento do sinal (n). Se definido, a entrada é truncada ou preenchida com zeros. |
| dimension | int64_t | Entrada | O eixo sobre o qual a FFT será aplicada. |
| normalization | int64_t | Entrada | Modo de normalização: 1 (nenhuma), 2 (1/n), 3 (1/sqrt(n)). |
| output | aclTensor* | Saída | Tensor de saída contendo os resultados complexos. |
| workspaceSize | uint64_t* | Saída | Tamanho necessário da memória auxiliar no dispositivo. |
| opExecutor | aclOpExecutor** | Saída | Gerenciador da execução do operador. |
Restrições e Comportamento
- Cálculo Determinístico: O operador
aclRfft1Dgarante resultados determinísticos por padrão. - Limites de N: O valor de
signalLengthdeve estar preferencialmente no intervalo [1, 4096] para otimização, com potências de 2 suportadas até 262144.
Exemplo de Integração (C++)
#include <iostream>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/acl_rfft1d.h"
#define ASSERT_SUCCESS(ret, msg) \
if (ret != ACL_SUCCESS) { \
fprintf(stderr, "[ERROR] %s. Code: %d\n", msg, ret); \
return ret; \
}
int main() {
int32_t devId = 0;
aclrtStream computeStream;
// Inicialização básica do ambiente Ascend
ASSERT_SUCCESS(aclInit(nullptr), "Falha no aclInit");
ASSERT_SUCCESS(aclrtSetDevice(devId), "Falha ao definir dispositivo");
ASSERT_SUCCESS(aclrtCreateStream(&computeStream), "Erro ao criar stream");
// Configuração dos tensores
std::vector<int64_t> shapeIn = {1, 1, 8};
std::vector<int64_t> shapeOut = {1, 1, 5, 2}; // Saída complexa representada por par de floats
std::vector<float> rawData = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
void *devIn = nullptr, *devOut = nullptr;
aclTensor *inputTensor = nullptr, *outputTensor = nullptr;
// Alocação e cópia de dados (Simplificado)
size_t inBytes = rawData.size() * sizeof(float);
aclrtMalloc(&devIn, inBytes, ACL_MEM_MALLOC_HUGE_FIRST);
aclrtMemcpy(devIn, inBytes, rawData.data(), inBytes, ACL_MEMCPY_HOST_TO_DEVICE);
// Criação dos objetos aclTensor
int64_t stridesIn[] = {8, 8, 1};
inputTensor = aclCreateTensor(shapeIn.data(), shapeIn.size(), ACL_FLOAT, stridesIn, 0, ACL_FORMAT_ND, shapeIn.data(), shapeIn.size(), devIn);
size_t outBytes = 10 * sizeof(float);
aclrtMalloc(&devOut, outBytes, ACL_MEM_MALLOC_HUGE_FIRST);
int64_t stridesOut[] = {10, 10, 2, 1};
outputTensor = aclCreateTensor(shapeOut.size() == 4 ? shapeOut.data() : nullptr, shapeOut.size(), ACL_FLOAT, stridesOut, 0, ACL_FORMAT_ND, shapeOut.data(), shapeOut.size(), devOut);
// Configurações da RFFT
int64_t n = 8;
int64_t dim = -1;
int64_t normMode = 1;
uint64_t wsSize = 0;
aclOpExecutor* handle = nullptr;
// Fase 1: Obter Workspace
auto status = aclRfft1DGetWorkspaceSize(inputTensor, n, dim, normMode, outputTensor, &wsSize, &handle);
ASSERT_SUCCESS(status, "Erro ao calcular workspace");
void* workspaceAddr = nullptr;
if (wsSize > 0) {
aclrtMalloc(&workspaceAddr, wsSize, ACL_MEM_MALLOC_HUGE_FIRST);
}
// Fase 2: Execução
status = aclRfft1D(workspaceAddr, wsSize, handle, computeStream);
ASSERT_SUCCESS(status, "Erro na execução do aclRfft1D");
aclrtSynchronizeStream(computeStream);
// Limpeza
aclDestroyTensor(inputTensor);
aclDestroyTensor(outputTensor);
aclrtFree(devIn);
aclrtFree(devOut);
if (workspaceAddr) aclrtFree(workspaceAddr);
aclrtDestroyStream(computeStream);
aclrtResetDevice(devId);
aclFinalize();
return 0;
}