AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77136876
Accepted
Bobby Ocean
Bobby Ocean
Asked: 2023-09-20 01:53:47 +0800 CST2023-09-20 01:53:47 +0800 CST 2023-09-20 01:53:47 +0800 CST

Finalizando o cálculo do Numpy antecipadamente

  • 772

Dadas duas grandes matrizes,

A = np.random.randint(10,size=(10000,2))
B = np.random.randint(10,size=(10000,2))

Gostaria de determinar se algum dos vetores tem um produto vetorial igual a zero. Nós poderíamos fazer

C = np.cross(A[:,None,:],B[None,:,:])

e então verifique se C contém 0 ou não.

not C.all()

No entanto, este processo requer o cálculo de todos os produtos cruzados, o que pode ser demorado. Em vez disso, eu preferiria deixar numpy realizar o produto vetorial, mas SE um zero for alcançado em qualquer ponto, simplesmente corte toda a operação e termine mais cedo. O numpy tem uma operação de "rescisão antecipada" que interromperá as operações numpy antecipadamente se elas atingirem uma condição? Algo como,

np.allfunc()
np.anyfunc()

O exemplo acima é um caso em que A e B têm uma probabilidade extremamente alta de ter um produto vetorial zero em algum ponto (na verdade, é muito provável que ocorra perto do início), tanto que a execução de um python-for-loop (eca!) é muito mais rápido do que usar o código altamente otimizado do numpy.

Em geral, qual é a maneira mais rápida de determinar se A e B têm produto vetorial zero?

python
  • 1 1 respostas
  • 40 Views

1 respostas

  • Voted
  1. Best Answer
    Jérôme Richard
    2023-09-20T06:08:40+08:002023-09-20T06:08:40+08:00

    O numpy tem uma operação de "rescisão antecipada" que interromperá as operações numpy antecipadamente se elas atingirem uma condição?

    Simplificando, não, Numpy não. Na prática, isso é um pouco mais complexo do que isso.


    Na verdade, a função allfuncand anyfuncque você propõe é semelhante a np.alland np.any. Essa função faz algum tipo de rescisão antecipada. Aqui está uma prova na minha máquina:

    v = np.random.randint(0, 2, 200*1024*1024) > 0
    
    # 2.74 ms ± 61.5 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    %timeit -n 10 v.all()
    
    # 3.16 ms ± 46.5 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    v[0:v.size//16] = True
    %timeit -n 10 v.all()
    
    # 3.72 ms ± 77.7 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    v[0:v.size//8] = True
    %timeit -n 10 v.all()
    
    # 4.64 ms ± 80.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    v[0:v.size//4] = True
    %timeit -n 10 v.all()
    
    # 6.67 ms ± 127 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    v[0:v.size//2] = True
    %timeit -n 10 v.all()
    
    # 10.5 ms ± 69.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    v[0:v.size] = True
    %timeit -n 10 v.all()
    

    O primeiro é tão rápido que não pode iterar por todo o array, já que a taxa de transferência da memória atingiria 71 GiB/s, enquanto minha RAM só pode atingir a largura de banda máxima teórica de 47,7 GiB/s (cerca de 40 GiB/s na prática). Meu cache de CPU está longe de ser grande o suficiente para armazenar uma parte significativa desse array e o array ocupa 200 MiB de RAM, então cada booleano ocupa 1 byte de RAM. Estranhamente, a velocidade alle anyé bastante decepcionante no primeiro caso, pois v[2]é Falsena prática. Numpy certamente executa o cálculo pedaço por pedaço e executa o encerramento antecipado somente após calcular um pedaço (se necessário).

    O problema com anye allé que eles exigem uma matriz booleana no parâmetro. Assim, a matriz booleana precisa ser totalmente computada primeiro, anulando o benefício de qualquer encerramento antecipado .


    Alternativamente, Numpy fornece ufuncs que são projetados para operar em arrays elemento por elemento. Um exemplo de ufunc é np.ufunc.reduce. Eles poderiam ser usados ​​para compor algoritmos de tal forma que o encerramento antecipado seria teoricamente possível. Esta solução seria significativamente mais rápida do que as operações normais não ufunc quando o encerramento é possível bem cedo. No entanto, quando o encerramento só é possível ultimamente, o ufuncs seria muito mais lento do que as operações não-ufunc. Na verdade, os ufuncs são (atualmente) fundamentalmente ineficientes em comparação com as operações não-ufunc. Isso ocorre porque os ufuncs exigem uma chamada de função cara (nativa) por item. Esta chamada de função, aplicada em itens escalares, evita diversas otimizações críticas como o uso deInstruções SIMD . Ainda assim, ufuncs muitas vezes pode ser mais rápido do que usar código Python puro elemento por elemento, graças a "vectorization" . A maneira atual como os ufuncs podem ser compostos é que o AFAIK não é suficiente, no seu caso de uso, para escrever um código eficiente que se beneficie do encerramento antecipado.


    A maneira padrão de encerrar antecipadamente no Numpy é dividir o cálculo em vários pedaços (manualmente). Essa solução geralmente é rápida porque é vetorizada, geralmente compatível com SIMD e eficiente em cache (assumindo que os pedaços sejam pequenos o suficiente). A sobrecarga do Numpy é pequena, desde que os pedaços sejam grandes o suficiente. Aqui está um exemplo:

    def compute_by_chunk(A, B):
        chunkSize = 256
        for i in range(0, A.size, chunkSize):
            for j in range(0, B.size, chunkSize):
                C = np.cross(A[i:i+chunkSize,None,:], B[None,j:j+chunkSize,:])
                if not C.all():
                    # print(f'Zero found in chunk ({i},{j})')
                    return True
        return False
    

    Para o seu exemplo de entrada, são necessários 239 µs na minha máquina, enquanto a implementação ingênua do Numpy leva 234 ms. Isso é cerca de 1000 vezes mais rápido neste caso. Com pedaços menores, como 32x32, o cálculo é ainda mais rápido: 32,3 µs.

    Na verdade, pedaços menores são melhores quando há muitos zeros (já que leva tempo para calcular o primeiro pedaço). 256x256 deve ser relativamente bom na maioria das máquinas (bastante amigável ao cache, eficiente em termos de memória e com baixa sobrecarga Numpy).


    Uma solução mais simples (que geralmente também é mais rápida) é usar módulos/ferramentas, como Cython ou Numba , compilando seu código para que os loops possam ser rápidos graças à compilação para funções nativas. No entanto, com esta solução, você mesmo precisa reimplementar o produto vetorial. Na verdade, o Numba ainda não oferece suporte e o Cython não será mais rápido (do que um código Python puro usando Numpy) se você apenas chamar funções Numpy em loops.

    • 2

relate perguntas

  • Como divido o loop for em 3 quadros de dados individuais?

  • Como verificar se todas as colunas flutuantes em um Pandas DataFrame são aproximadamente iguais ou próximas

  • Como funciona o "load_dataset", já que não está detectando arquivos de exemplo?

  • Por que a comparação de string pandas.eval() retorna False

  • Python tkinter/ ttkboostrap dateentry não funciona quando no estado somente leitura

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve