Eu queria saber se existe um método rápido e eficiente para encontrar antecipadamente o número de não-zeros para operações de multiplicação de matrizes esparsas, assumindo que ambas as matrizes estejam no formato CSC ou CSR.
Eu sei que existe um no pacote smmp, mas preciso de algo que já esteja implementado em C ou C ++.
Qualquer ajuda será apreciada. Desde já, obrigado.
matrix
sparse-matrix
Recker
fonte
fonte
Respostas:
Você pode apenas simular o produto matriz-matriz, formando o produto dos dois padrões de escarsidade - ou seja, você considera o padrão de esparsidade (armazenado em matrizes separadas no formato CSR) como uma matriz que contém zero ou um em cada entrada. A execução deste produto simulado requer apenas a formação do eoperação nesses zeros e uns e, portanto, é muito mais rápido que o produto matriz-matriz real - na verdade, tudo o que você precisa fazer é percorrer as linhas e colunas das duas matrizes e verificar se há pelo menos uma entrada em um linha e coluna com a qual você se multiplica, onde ambas as matrizes são diferentes de zero. Essa é uma operação barata - muito mais barata do que realmente a multiplicação de ponto flutuante no produto real, que exige não apenas que você faça aritmética de ponto flutuante (caro), mas também leia os números reais de ponto flutuante da memória ( ainda mais caro, mas você não precisa disso ao multiplicar o padrão de dispersão, porque os valores diferentes de zero da matriz são armazenados separadamente no CSR).
fonte
Na verdade, eu escrevi o código original no Matlab para A * B, A e B esparsos. A pré-alocação de espaço para o resultado foi realmente a parte interessante. Observamos o que Godric aponta - que conhecer o número de não-zeros na AB é tão caro quanto a computação da AB.
Fizemos a implementação inicial do escasso Matlab por volta de 1990, antes do artigo de Edith Cohen que dava a primeira maneira prática e rápida de estimar com precisão o tamanho da AB. Reunimos um estimador de tamanho inferior e, se ficarmos sem espaço no meio da computação, dobramos a alocação e copiamos o resultado parcialmente calculado.
Não sei o que há no Matlab agora.
Outra possibilidade seria calcular AB uma coluna por vez. Cada coluna pode ser armazenada temporariamente em um acumulador esparso (consulte o artigo esparso do Matlab para obter uma explicação sobre isso) e espaço alocado para armazenar o tamanho exatamente conhecido da coluna de resultados. O resultado seria na forma de coluna dispersa e compactada dispersa - cada coluna no CSC, mas sem contiguidade entre colunas - usando 2 vetores de numcols de comprimento (início da coluna, comprimento da coluna), em vez de um, como metadados. É uma forma de armazenamento que pode valer uma olhada; tem outra força - você pode aumentar uma coluna sem realocar toda a matriz.
fonte
Este artigo descreve um algoritmo para aproximar o tamanho de uma resultante do produto da matriz de duas matrizes esparsas.
O problema de encontrar um número exato de entradas diferentes de zero em uma multiplicação de matriz esparsa é que cada elemento resultante depende da interação de dois vetores, sendo provável que ambos contenham pelo menos alguns elementos diferentes de zero. Portanto, para calcular o número, é necessário avaliar as operações lógicas em um par de vetores para cada elemento no resultante. O problema disso é que requer um número de operações semelhante ao número de operações necessárias para calcular o próprio produto da matriz. Nos meus comentários, mencionei a possibilidade de explorar certas estruturas nos elementos diferentes de zero das matrizes originais, no entanto, essas mesmas explorações poderiam ser usadas para reduzir também o trabalho realizado na multiplicação de matrizes.
Provavelmente, seria melhor usar o papel acima para superestimar os requisitos de memória, fazer a multiplicação e truncar a memória alocada ou mover a matriz resultante para uma matriz de tamanho mais apropriado. Além disso, produtos de matriz esparsa não são uma ocorrência rara e eu quase garantiria que esse problema já havia sido resolvido antes. Uma pequena escavação em algumas bibliotecas de matriz esparsas de código aberto deve levar você aos algoritmos que eles usam para pré-alocar memória.
fonte
Para CSR ou CSC, você tem certeza de que sua matriz de elementos da matriz já não possui zeros? Nesse caso, é simples descobrir quantos elementos diferentes de zero existem, usando algo semelhante a:
No entanto, se esse não for o caso (parece um pouco fácil), o que você pode tentar é uma redução . Se sua matriz de elementos da matriz for muito grande, talvez seja a maneira mais eficiente de calcular o número de elementos diferentes de zero. Muitas bibliotecas C / C ++ paralelas, como Thrust (uma biblioteca CUDA) ou OpenCL (que você não precisa de uma GPU para usar) têm suporte para reduções condicionais - para cada elemento, adicione o resultado de
Condition(Element)
. Se você definir a condição paraElement != 0
, adicionará o número de elementos diferentes de zero. Você também pode remover os elementos com valor zero de sua matriz de elementos, matriz de índices de linha / coluna e ajustar os ponteiros de coluna / linha.fonte
A maneira mais simples de implementar a RSE é tentar
para representar sua matriz. Nesse caso, você realmente não se preocupará com o número de elementos diferentes de zero, tudo será acessado via
em cada linha. Melhor ..
fonte