Numpy: O tipo de int padrão depende da plataforma

Criado em 26 jul. 2017  ·  12Comentários  ·  Fonte: numpy/numpy

np.array([1]).dtype depende da plataforma, presumivelmente porque o padrão é np.int_

  1. Isso é intencional?
  2. Se não, podemos forçá-lo a int64 ?
23 - Wish List 54 - Needs decision numpy.dtype

Comentários muito úteis

Devemos pensar seriamente em mudar isso.

Na minha experiência, se uma biblioteca Python de complexidade moderada que usa o NumPy não executa testes específicos do Windows, provavelmente ela está danificada por esse motivo.

Todos 12 comentários

É por design - a ideia é que o tipo int padrão de numpy corresponde ao intervalo de int do python 2, que por sua vez corresponde ao long do compilador da plataforma C.

Se este é um bom design é outra questão, especialmente porque o python 3 eliminou isso. Houve discussões intermitentes sobre alterá-lo antes que você provavelmente pode desenterrar - especialmente a forma confusa e propensa a erros que o padrão é 32 bits no win64.

Suponho que uma maneira de levar essa discussão adiante seria testar se algum pacote principal quebra se você fizer essa alteração.

Uma coisa que pode falhar é se alguém estiver usando dtype = int e presumir que isso está de alguma forma relacionado ao tipo longo C ...

Alterar o tipo de int padrão no Windows 64 para 64 bits seria uma alteração importante o suficiente para garantir a quebra do software.
O comportamento atual causa muitos bugs.

O fato de o tipo int padrão em 32 bits ser de 32 bits provavelmente não é tão ruim, já que pelo menos cobre todo o intervalo endereçável e alterá-lo pode ter impacto no desempenho.

Devemos pensar seriamente em mudar isso.

Na minha experiência, se uma biblioteca Python de complexidade moderada que usa o NumPy não executa testes específicos do Windows, provavelmente ela está danificada por esse motivo.

@shoyer : Encontramos exatamente esse problema no Windows com @MichaelMauderer em https://github.com/colour-science/colour/pull/431.

Eu estava presumindo incorretamente que np.int_ era independente de plataforma.

Talvez devêssemos eliminar esse padrão ao mesmo tempo que python 2, uma vez que a única razão para padronizar para np.int_ era que ele correspondia ao tamanho de builtins.int , o que em python 3 nem mesmo é verdade.

Idealmente, o numpy deve se comportar da mesma maneira em todas as plataformas. Um colega meu usa o Windows e recentemente teve que passar algum tempo tentando descobrir por que um programa estava produzindo resultados diferentes em sua máquina e no meu Mac. As considerações de desempenho da IMO empalidecem em comparação com a obtenção de resultados corretos e consistentes.

Existe alguma solução de tempo de execução que um usuário possa executar, antes de seu outro código, para forçar os tipos padrão numpy-on-Windows para as mesmas larguras que em qualquer lugar? (Talvez, um mapeamento adulterável e orientado por dados de tipos Python para tipos entorpecidos?)

Como um novo exemplo de algumas das loucuras resultantes, pedir especificamente por uma matriz de um tipo compatível com type(2**32) resultados em uma matriz que não pode armazenar 2**32 :

2020-07-07T06:53:20.9528159Z     def testTiny(self):
2020-07-07T06:53:20.9528423Z         a = np.empty(1, dtype=type(2**32))
2020-07-07T06:53:20.9529046Z >       a[0] = 2**32
2020-07-07T06:53:20.9529318Z E       OverflowError: Python int too large to convert to C long

@gojomo Não tenho certeza se essa é uma abordagem correta de qualquer maneira. Em python 3, type(2**32) é garantidamente int , então essa é apenas uma maneira mais complicada de dizer dtype=int . Se você estiver usando um literal como esse, é claro que você pode usar dtype=np.int64 explícito.

Para torná-lo mais dinâmico, dtype=np.array(2**32).dtype funciona? (É provável que existam maneiras ainda mais idiomáticas de fazer isso.)
EDITAR: np.empty_like(2**32, shape=...) provavelmente é isso, supondo que funcione.

Não, eu tinha um PR para adicionar um, talvez eu possa abri-lo novamente agora que decidimos iniciar a suspensão de uso em alguns dos aliases: https://github.com/numpy/numpy/pull/16535

Portanto, use dtype=np.intp que dá a você 32 bits em sistemas de 32 bits e 64 bits em sistemas de 64 bits, ou use dtype=np.int64 para começar. Esse PR tornou dtype=np.intp o padrão, que é a alteração mais simples, porque intp é bastante comum em NumPy.

Eu estava pensando que, se o NEP 31 acontecer, isso também tornaria esse tipo de substituição de padrões facilmente opt-in.

@adeak Meu snippet não é um exemplo literal; meu problema real é que tenho uma lista de muitos ints, que eventualmente chega a 2 32, mas uma matriz numpy digitada com base no primeiro int quebra no Windows quando chega a 2 32, mas funciona em qualquer outro lugar.

(Eu esperava que o snippet destacasse alguns dos absurdos aparentes da interação Python-para-numpy: um tipo relatado para um número específico não deveria comunicar especificamente um tipo correspondente com largura suficiente para armazená-lo? Mas suponho que Python contribui igualmente para o problema, já que 2**65 & 2**129 tem o mesmo problema de relatar como int simples. Portanto, é mais uma provocação do que um guia para melhorar comportamento.)

Eu responderia à pergunta "a escolha do numpy é um bom design?" pergunta no comentário de @njsmith de 2017 como: "É razoável voltar quando, mas não mais, com Python3, e a primazia dos sistemas de 64 bits, e a própria eliminação da Microsoft do suporte do WIndows 10 para sistemas de 32 bits."

Desde então, o tráfego neste problema parece ter feito referência a muitos lugares, o que causou problemas para as pessoas, mas ainda não há nenhum exemplo existente de código que quebraria com um padrão alterado. (Provavelmente há algum, em algum lugar.)

Se o mergulho de mudar o padrão de uma só vez é muito arriscado, uma chamada que opta por algum padrão de largura mínima (ou padrão escolhido pelo usuário) para todos os mapeamentos subsequentes de int do Python pode ajudar. (E então, em algum momento posterior, com um aviso aos usuários do Windows, altere o padrão, mas dê aos retardatários a opção de alterá-lo de volta por um tempo.)

Esta página foi útil?
0 / 5 - 0 avaliações