Numpy: Prise en charge de la coercition des canards

Créé le 25 juin 2019  ·  55Commentaires  ·  Source: numpy/numpy

Ouverture de ce numéro après une discussion avec @shoyer , @pentschev et @mrocklin en question (https://github.com/dask/dask/issues/4883). AIUI cela a été discuté dans la NEP 22 (donc je parrot principalement les idées des autres ici pour renouveler la discussion et corriger mon propre malentendu;).

Il serait utile que diverses bibliothèques de tableaux en aval aient une fonction pour s'assurer que nous avons un tableau de canard (comme ndarray ). Ce serait un peu similaire à np.asanyarray , mais sans l'exigence de sous-classification. Cela permettrait aux bibliothèques de renvoyer leur propre type de tableau (canard) . Si aucune conversion appropriée n'était prise en charge par l'objet, nous pourrions revenir en arrière pour gérer les sous-classes ndarray , ndarray s et la coercition d'autres choses (listes imbriquées) en ndarray s.

cc @njsmith (co-auteur de NEP 22)

01 - Enhancement numpy.core

Commentaire le plus utile

Peut-être quack_array :)

Tous les 55 commentaires

L'implémentation proposée ressemblerait à ceci:

import numpy as np

# hypothetical np.duckarray() function
def duckarray(array_like):
  if hasattr(array_like, '__duckarray__'):
    # return an object that can be substituted for np.ndarray
    return array_like.__duckarray__()
  return np.asarray(array_like)

Exemple d'utilisation:

class SparseArray:
  def __duckarray__(self):
    return self
  def __array__(self):
    raise TypeError

np.duckarray(SparseArray())  # returns a SparseArray object
np.array(SparseArray())  # raises TypeError

Ici, j'ai utilisé np.duckarray et __duckarray__ comme espaces réservés, mais nous pouvons probablement faire mieux pour ces noms. Voir la terminologie de NEP 22:

"Duck array" fonctionne bien comme espace réservé pour le moment, mais c'est assez jargon et peut dérouter les nouveaux utilisateurs, donc nous pouvons vouloir choisir autre chose pour les fonctions de l'API réelles. Malheureusement, «comme un tableau» est déjà pris pour le concept de «tout ce qui peut être forcé dans un tableau» (y compris par exemple des objets de liste), et «anyarray» est déjà pris pour le concept de «quelque chose qui partage l'implémentation de ndarray, mais a une sémantique différente », qui est l'opposé d'un tableau canard (par exemple, np.matrix est un« anyarray », mais n'est pas un« tableau canard »). Il s'agit d'un abri à vélos classique, donc pour l'instant nous n'utilisons que le «canard array». Certaines options possibles incluent: arrayish, pseudoarray, nominalarray, ersatzarray, arraymimic,…

Quelques autres idées de noms: np.array_compatible() , np.array_api() ....

np.array_compatible pourrait fonctionner, même si je ne suis pas sûr que je l'aime mieux que duckarray . np.array_api Je n'aime pas, donne une mauvaise idée à mon humble avis.

Depuis longtemps, nous n'avons pas trouvé de meilleur nom, peut-être devrions-nous simplement bénir le nom "duck-array" ......

J'aime le mot compatible, peut-être que nous pouvons également penser à des variations le long de cette ligne as_compatible_array (implique un peu que tous les objets compatibles sont des tableaux). Le as est peut-être ennuyeux (en partie parce que toutes les fonctions as n'ont pas d'espace). "duck" semble bien dans les bibliothèques, mais je trouve un peu étrange pour les gens au hasard qui le voient. Donc je pense que je n'aime pas "canard" si et seulement si nous voulons que les utilisateurs en aval l'utilisent beaucoup (c'est-à-dire même quand je commence à écrire un petit outil pour moi / un petit laboratoire).

Peut-être quack_array :)

Pour approfondir un peu le sujet, il existe un autre cas qui n'est pas couvert par np.duckarray , qui est la création de nouveaux tableaux avec un type basé sur un type existant, similaire à quelles fonctions telles que np.empty_like faire. Actuellement, nous pouvons faire des choses comme ceci:

>>> import numpy as np, cupy as cp
>>> a  = cp.array([1, 2])
>>> b = np.ones_like(a)
>>> type(b)
<class 'cupy.core.core.ndarray'>

D'un autre côté, si nous avons un array_like que nous aimerions créer un tableau CuPy à partir de l'API de NumPy, ce n'est pas possible. Je pense qu'il serait utile d'avoir quelque chose comme:

import numpy as np, cupy as cp
a  = cp.array([1, 2])
b = [1, 2]
c = np.asarray(b, like=a)

Des idées / suggestions à ce sujet?

Peut-être np.copy_like? Nous voudrions définir soigneusement quelles propriétés
(par exemple, y compris dtype ou non) sont copiés à partir de l'autre tableau.

Le lun.1 juillet 2019 à 05:40 Peter Andreas Entschev <
[email protected]> a écrit:

Pour approfondir un peu le sujet, il y a un autre cas qui n'est pas couvert
avec np.duckarray, qui est la création de nouveaux tableaux avec un type basé
sur un type existant, similaire à ce que font des fonctions telles que np.empty_like.
Actuellement, nous pouvons faire des choses comme ceci:

import numpy comme np, cupy comme cp >>> a = cp.array ([1, 2]) >>> b = np.ones_like (a) >>> type (b)

D'un autre côté, si nous avons un array_like que nous aimerions créer
un tableau CuPy depuis l'API de NumPy, ce n'est pas possible. Je pense que ce serait
utile d'avoir quelque chose comme:

importer numpy comme np, cupy comme cp
a = cp.array ([1, 2])
b = [1, 2]
c = np.asarray (b, comme = a)

Des idées / suggestions à ce sujet?

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/numpy/numpy/issues/13831?email_source=notifications&email_token=AAJJFVRCWDHRAXHHRDHXXM3P5H3LRA5CNFSM4H3HQWAKYY3PNVWWK3TUL52HS4DFVom7GVWWWK3TUL52HS4DFVom
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAJJFVRSYHUYHMPWQTW2NLLP5H3LRANCNFSM4H3HQWAA
.

np.copy_like sonne bien aussi. Je suis d'accord, nous devrions probablement avoir des moyens de contrôler des choses telles que dtype .

Désolé pour la question du débutant, mais quelque chose comme np.copy_like devrait-il être un amendement à NEP-22, devrait-il être discuté dans la liste de diffusion, ou quelle serait l'approche la plus appropriée pour cela?

Nous n'avons pas vraiment de règles strictes à ce sujet, mais je pencherais pour mettre ensemble np.copy_like et np.duckarray (ou peu importe comment nous l'appelons) dans un nouveau NEP sur la contrainte / création de tableaux de canards, un c'est prescriptif comme NEP 18 plutôt que "Informatif" comme NEP 22. Cela n'a pas besoin d'être long, la plupart des motivations sont déjà claires en faisant référence à NEP 18/22.

Une note à propos de np.copy_like() : il devrait certainement être distribué avec __array_function__ (ou quelque chose comme ça), donc des opérations comme np.copy_like(sparse_array, like=dask_array) pourraient être définies sur l'un ou l'autre type de tableau.

Super, merci pour l'info, et je suis d'accord avec votre proposition d'expédition. Je vais travailler sur un NEP pour la mise en œuvre de np.duckarray et np.copy_like et soumettre un projet de PR cette semaine pour cela.

Génial, merci Peter!

Le lun.1 juillet 2019 à 09:29 Peter Andreas Entschev <
[email protected]> a écrit:

Super, merci pour l'info, et je suis d'accord avec votre proposition d'expédition. je
travaillera sur un NEP pour la mise en œuvre de np.duckarray et
np.copy_like et soumettez un projet de PR cette semaine pour cela.

-
Vous recevez cela parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/numpy/numpy/issues/13831?email_source=notifications&email_token=AAJJFVW2YUBNUCJZK6JWDBTP5IWHNA5CNFSM4H3HQWAKYY3PNVWWWK3TUL52HS4DFV73PNVWWWK3TUL52HS4DFV73PNVWWWK3TUL52HS4DFV73PNVWWWK3TUL52HS4DFV73PNVWWWK3TUL52HS4DFV73NVWWWK3TUL52HS4DFV73GNVWWWK3TUL52HS4DFV73GNVWWWK3TUL52HS4DFV73
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAJJFVR2KTPAZ4JPWDYYMFLP5IWHNANCNFSM4H3HQWAA
.

Mon plaisir et merci beaucoup pour les idées et le soutien dans ce travail!

Les fonctions array_like et copy_like seraient un peu bizarres à avoir dans l'espace de noms principal, je pense, car nous ne pouvons pas avoir d'implémentation par défaut (du moins pas une qui ferait le bon choix pour cupy / dask / sparse / etc), non? Ils ne sont utiles que lorsqu'ils sont remplacés. Ou est-ce que je manque un moyen de créer des objets de tableau arbitraires non numpy ici?

C'est vrai, cela ne serait vraiment utile que si vous souhaitez prendre en charge le typage canard. Mais certainement np.duckarray et np.copy_like fonctionneraient même si les arguments ne sont que des tableaux NumPy - ils seraient juste équivalents à np.array / np.copy .

Toutes les implémentations de tableaux ont une méthode copy , n'est-ce pas? Utiliser cela au lieu de copy_like devrait fonctionner, alors pourquoi ajouter une nouvelle fonction?

array_like Je peux voir la nécessité de, mais nous voudrons peut-être discuter de l'endroit où le mettre.

np.duckarray sens pour moi.

Je pencherais vers le regroupement de np.copy_like et np.duckarray (ou peu importe ce que nous appelons) dans un nouveau NEP sur la contrainte / création de tableaux de canard, qui est normatif comme NEP 18 plutôt que "Informational" comme NEP 22.

+1

array_like Je peux voir la nécessité de, mais nous voudrons peut-être discuter de l'endroit où le mettre.

C'est en fait le cas que j'aimerais aborder avec quelque chose comme np.copy_like . Je n'ai pas testé, mais probablement np.copy distribue déjà correctement si le tableau n'est pas NumPy.

Pour être clair, faites-vous référence également à une fonction np.array_like ? J'ai intentionnellement évité un tel nom parce que je pensais qu'il pouvait être déroutant pour toutes les références existantes à array_like -arrays. Cependant, je réalise maintenant que np.copy_like peut impliquer une copie nécessaire, et je pense qu'il serait bon d'avoir un comportement similaire à np.asarray , où la copie ne se produit que si ce n'est pas déjà un NumPy tableau. Dans le cas discuté ici, le mieux serait de ne faire la copie que si a n'est pas du même type que b dans un appel tel que np.copy_like(a, like=b) .

Je n'ai pas testé, mais probablement np.copy distribue déjà correctement si le tableau n'est pas NumPy.

Il devrait, il est décoré pour prendre en charge __array_function__ .

Pour être clair, faites-vous référence également à une fonction np.array_like ? J'ai intentionnellement évité un tel nom parce que je pensais qu'il pouvait être déroutant pour toutes les références existantes à array_like-arrays.

Oui. Et oui d'accord, cela peut être déroutant.

Cependant, je réalise maintenant que np.copy_like peut impliquer une copie nécessaire,

Oui, ce nom implique une copie de données.

peut impliquer une copie nécessaire, et je pense qu'il serait bon d'avoir un comportement similaire à np.asarray ,

Je pensais que c'était np.duckarray .

Je pense que l'exemple de Peter ci - np.copy_like pour plus de simplicité.

import numpy as np, cupy as cp
a  = cp.array([1, 2])
b = [1, 2]
c = np.copy_like(b, like=a)

Je pensais que c'était np.duckarray.

En fait, np.duckarray ne fera essentiellement rien et renverra simplement le tableau lui-même (s'il est remplacé), sinon retournera np.asarray (conduisant à un tableau NumPy). Nous ne pouvons pas obtenir un tableau CuPy à partir d'une liste Python avec, par exemple. Nous avons toujours besoin d'une fonction qui peut être distribuée à CuPy (ou à tout autre tableau like= ) pour un array_like .

Merci @jakirkham pour l'exemple mis à jour.

c = np.copy_like(b, like=a)

Cela sera donc envoyé à CuPy via a.__array_function__ et échouera si cet attribut n'existe pas (par exemple, a=<scipy.sparse matrix> ne fonctionnerait pas)? Il semble que nous ayons besoin d'un nouvel espace de noms ou d'un nouveau package d'utilitaires d'interopérabilité pour ce genre de choses. Soit cela, soit laissez-le à un futur mécanisme de répartition plus complet où l'on pourrait simplement faire:

with cupy_backend:
   np.array(b)

L'introduction de nouvelles fonctions dans l'espace de noms principal qui n'a pas de sens pour NumPy lui-même de prendre en charge le contournement d'une limitation de __array_function__ semble un peu malsaine ....

Cela va donc être envoyé à CuPy via a.__array_function__ et échouer si cet attribut n'existe pas (par exemple, a=<scipy.sparse matrix> ne fonctionnerait pas)?

Je ne dirais pas que cela doit nécessairement échouer. Nous pourrions utiliser par défaut NumPy et lever un avertissement (ou ne pas le lever du tout), par exemple.

Il semble que nous ayons besoin d'un nouvel espace de noms ou d'un nouveau package d'utilitaires d'interopérabilité pour ce genre de choses. Soit cela, soit laissez-le à un futur mécanisme de répartition plus complet

Ce serait certainement bien d'avoir un mécanisme de distribution complet, mais j'imagine que cela n'a pas été fait auparavant en raison de sa complexité et de problèmes de compatibilité descendante? Je n'étais pas là quand les discussions ont eu lieu, donc juste deviner.

L'introduction de nouvelles fonctions dans l'espace de noms principal qui n'a pas de sens pour NumPy lui-même de prendre en charge le contournement d'une limitation de __array_function__ semble un peu malsaine ...

Je comprends certainement votre point de vue, mais je pense aussi que si nous éloignons trop de choses de l'espace de noms principal, cela pourrait effrayer les utilisateurs. Peut-être que je me trompe et ce n'est qu'une impression. Quoi qu'il en soit, je ne propose pas du tout d'implémenter des fonctions qui ne fonctionneront pas avec NumPy, mais peut-être seulement pas absolument nécessaires lorsque vous utilisez NumPy seul.

L'introduction de nouvelles fonctions dans l'espace de noms principal qui n'a pas de sens pour NumPy lui-même de prendre en charge le contournement d'une limitation de __array_function__ semble un peu malsaine ...

En fait, dans ce sens, np.duckarray n'appartiendrait pas non plus à l'espace de noms principal.

En fait, dans ce sens, np.duckarray n'appartiendrait pas non plus à l'espace de noms principal.

Je pense que l'un est plus défendable (analogue à asarray et il vérifierait essentiellement "est-ce que cela correspond à notre définition d'un type de canard de type ndarray"), mais oui. Si nous voulons également exposer array_function_dispatch , et que nous avons des choses np.lib.mixins.NDArrayOperatorsMixin et que nous prévoyons d'écrire plus de mixins, un nouveau sous-module sensible pour tout ce qui concerne l'interopérabilité pourrait avoir du sens.

Ce serait certainement bien d'avoir un mécanisme de distribution complet, mais j'imagine que cela n'a pas été fait auparavant en raison de sa complexité et de problèmes de compatibilité descendante? Je n'étais pas là quand les discussions ont eu lieu, donc juste deviner.

Je pense qu'il y a plusieurs raisons. __array_function__ est similaire à ce que nous avions déjà, il est donc plus facile de raisonner. Il a de faibles frais généraux. Il pourrait être conçu et mis en œuvre sur une échelle de temps d'environ 6 mois, et @shoyer a

un nouveau sous-module sensé pour tout ce qui concerne l'interopérabilité pourrait avoir un sens.

Aucune objection réelle de ma part, je pense qu'il vaut mieux avoir des fonctionnalités quelque part plutôt que nulle part. :)

Je pense qu'il y a plusieurs raisons. __array_function__ est similaire à ce que nous avions déjà, il est donc plus facile de raisonner. Il a de faibles frais généraux. Il pourrait être conçu et mis en œuvre sur une échelle de temps d'environ 6 mois, et @shoyer a

Mais si nous voulons tirer parti de __array_function__ plus largement, avons-nous d'autres alternatives maintenant pour implémenter des choses comme np.duckarray et np.copy_like (ou quoi que nous décidions de l'appeler)? Je suis ouvert à toutes les alternatives, mais pour le moment, je n'en vois aucune, bien sûr, plutôt que d'utiliser la méthode de distribution complète, ce qui prendra probablement beaucoup de temps et limitera la portée de __array_function__ énormément (et le rend pratiquement impossible pour la plupart des cas les plus complexes que j'ai vus).

Mais si nous voulons tirer parti de __array_function__ plus largement, avons-nous d'autres alternatives maintenant pour implémenter des choses comme np.duckarray et np.copy_like (ou quoi que nous décidions de l'appeler)?

Je pense que vous avez en effet besoin d'un ensemble de fonctionnalités utilitaires comme celle-là, pour passer de la couverture d'une fraction des cas d'utilisation à> 80% des cas d'utilisation. Je ne pense pas qu'il y ait moyen de contourner cela. Je n'aime tout simplement pas encombrer l'espace de noms principal, alors proposez de trouver un meilleur endroit pour ceux-ci.

Je suis ouvert à toutes les alternatives, mais pour le moment, je n'en vois aucune, bien sûr, plutôt que d'utiliser la méthode de distribution complète, ce qui prendra probablement beaucoup de temps et limitera la portée de __array_function__ énormément (et le rend pratiquement impossible pour la plupart des cas les plus complexes que j'ai vus).

Je veux dire, nous bouchons juste quelques trous évidents ici, non? Nous n'allons jamais couvrir tous les «cas les plus complexes». Supposons que vous souhaitiez remplacer np.errstate ou np.dtype , cela ne se produira tout simplement pas avec l'approche basée sur le protocole.

En ce qui concerne les alternatives, uarray n'est pas encore là et je ne suis pas encore convaincu que le surcoût sera suffisamment bas pour être utilisé par défaut dans NumPy, mais il se rapproche et nous sommes sur le point de l'essayer pour créer le scipy.fft Système backend https://github.com/Quansight-Labs/uarray/tree/master/unumpy

L'approche de répartition avec uarray est certainement intéressante. Bien que je sois toujours préoccupé par la façon dont nous gérons les méta-tableaux (comme Dask, xarray, etc.). Veuillez consulter ce commentaire pour plus de détails. Il n'est pas clair que cela a été résolu (veuillez me corriger si j'ai manqué quelque chose). Je serais intéressé à travailler avec d'autres chez SciPy pour essayer de déterminer comment nous résolvons ce problème.

Veuillez consulter ce commentaire pour plus de détails. Il n'est pas clair que cela a été résolu (veuillez me corriger si j'ai manqué quelque chose).

Je pense que les changements de la semaine dernière résolvent cela, mais pas sûr - laissons cela pour un autre fil.

Je serais intéressé à travailler avec d'autres chez SciPy pour essayer de déterminer comment nous résolvons ce problème.

Je serai là, ce serait formidable de vous rencontrer en personne.

Peut-être que np.coerce_like() ou np.cast_like() serait un meilleur nom que copy_like , de sorte qu'il soit clair que des copies ne sont pas nécessairement nécessaires. La fonctionnalité souhaitée est en effet assez similaire à la méthode .cast() , sauf que nous voulons convertir des types de tableaux ainsi que des dtypes, et cela devrait être une fonction plutôt qu'un protocole afin de pouvoir être implémenté par l'un ou l'autre des arguments.

L'approche de répartition avec uarray est certainement intéressante. Bien que je sois toujours préoccupé par la façon dont nous gérons les méta-tableaux (comme Dask, xarray, etc.).

uarray prend en charge plusieurs backends, donc quelque chose comme ça devrait fonctionner

with ua.set_backend(inner_array_backend), ua.set_backend(outer_array_backend):
  s = unumpy.sum(meta_array)

Cela pourrait être fait en appelant le méta-tableau ua.skip_backend intérieur de son implémentation, ou si le backend du méta-tableau renvoie NotImplemented en cas d'incompatibilité de type.

cc: @hameerabbasi

Je vais développer ceci: En règle générale, pour dask.array , tout ce qui contient da serait écrit sans skip_backend. Tout ce avec NumPy aurait besoin d'un skip_backend.

Ou pour da vous pouvez toujours ignorer l'envoi et appeler votre propre implémentation directement et avoir skip_backend(dask.array) partout.

En ce qui concerne la répartition des fonctions qui n'ont pas de tableau attaché, comme ones , cast , vous devez simplement définir un backend et avoir terminé. Idem pour np.errstate et np.dtype . Il existe un exemple couvrant np.ufunc dans unumpy .

En ce qui concerne le problème d'origine, uarray fournit le protocole __ua_convert__ , qui fait exactement cela. Une alternative serait que les backends remplacent directement asarray .

Merci pour les informations sur uarray , @rgommers , @ peterbell10 , @hameerabbasi.

Mais comme je le vois, vous _devez_ définir le bon backend avant de lancer le calcul, est-ce correct? L'un des avantages de __array_function__ est que les bibliothèques peuvent être totalement indépendantes des autres bibliothèques, comme Dask n'a pas besoin de connaître l'existence de CuPy, par exemple.

@pentschev C'était le cas jusqu'à récemment, lorsque nous avons ajouté la possibilité d '«enregistrer» un backend, mais nous recommandons que seul NumPy (ou une implémentation de référence) le fasse. Ensuite, les utilisateurs utilisant Dask n'auraient besoin que d'un seul set_backend.

Compris , je suppose que c'est ce que https://github.com/numpy/numpy/issues/13831#issuecomment -507432311, pointant vers les backends dans https://github.com/Quansight-Labs/uarray / tree / master / unumpy.

Désolé pour tant de questions, mais que se passe-t-il si une application hypothétique repose sur divers backends, par exemple, à la fois NumPy et Sparse, où en fonction de l'entrée de l'utilisateur, peut-être que tout sera NumPy uniquement, Sparse uniquement ou un mélange des deux. @ peterbell10 a mentionné que plusieurs backends sont pris en charge https://github.com/numpy/numpy/issues/13831#issuecomment -507458331, mais la sélection du backend peut-elle être rendue automatique ou faudrait-il gérer les trois cas séparément?

Donc, dans ce cas, vous devriez idéalement enregistrer NumPy, utiliser un gestionnaire de contexte pour Sparse et renvoyer NotImplemented de sparse le cas échéant, ce qui ferait un retour vers NumPy.

Chez SciPy @rgommers , @danielballan et moi-même avons parlé de ce problème. Nous avons conclu qu'il serait utile de procéder à l'ajout de duckarray (en utilisant ce nom). Cela dit, il semblait que ce serait prévu pour 1.18. Veuillez me corriger si j'ai mal compris les choses. Compte tenu de cela, serait-il bien de démarrer un PR?

Nous avons conclu qu'il serait utile de procéder à l'ajout de duckarray (en utilisant ce nom). Cela dit, il semblait que ce serait prévu pour 1.18. Veuillez me corriger si j'ai mal compris les choses. Compte tenu de cela, serait-il bien de démarrer un PR?

Tout cela me semble bien, mais il serait bon de commencer par une courte NEP énonçant la proposition exacte. Voir https://github.com/numpy/numpy/issues/13831#issuecomment -507334210

Bien sûr, cela a du sens. 🙂

En ce qui concerne le point de copie qui a été soulevé précédemment, je suis curieux de savoir si cela n'est pas résolu par les mécanismes existants. En particulier, qu'en est-il de ces lignes?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Certes, ce serait bien de ramener cela à une ligne. Je suis simplement curieux de savoir si cela fonctionne déjà pour ce cas d'utilisation ou si des éléments nous manquent.

Nous avons conclu qu'il serait utile de procéder à l'ajout du canard (en utilisant ce nom).

Tout cela me semble bien, mais il serait bon de commencer par une courte NEP énonçant la proposition exacte. Voir # 13831 (commentaire)

J'ai déjà commencé à écrire cela, mais je n'ai pas encore pu le terminer (désolé pour ma mauvaise planification https://github.com/numpy/numpy/issues/13831#issuecomment-507336302).

En ce qui concerne le point de copie qui a été soulevé précédemment, je suis curieux de savoir si cela n'est pas résolu par les mécanismes existants. En particulier, qu'en est-il de ces lignes?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Certes, ce serait bien de ramener cela à une ligne. Je suis simplement curieux de savoir si cela fonctionne déjà pour ce cas d'utilisation ou si des éléments nous manquent.

Vous pouvez le faire, mais cela peut nécessiter une logique de copie spéciale (comme dans CuPy https://github.com/cupy/cupy/pull/2079).

Cela dit, une fonction de copie peut être préférable, pour éviter que ce type de code supplémentaire ne soit nécessaire.

D'un autre côté, ce serait une sorte de remplacement de asarray . Je me demandais donc si au lieu d'une nouvelle fonction copy_like , nous voudrions plutôt revoir l' idée suggérée par NEP-18 :

Ceux-ci auront besoin de leurs propres protocoles:
...
array et asarray, car ils sont explicitement destinés à la contrainte sur un objet numpy.ndarray réel.

S'il y a une chance que nous aimerions revoir cela, il vaudrait peut-être mieux commencer un nouveau fil. Des idées, suggestions, objections?

Juste pour être clair sur mon commentaire ci-dessus, je ne sais pas moi-même si un nouveau protocole est une bonne idée (probablement de nombreux détails encombrants que je ne prévois pas impliqués), je me demande vraiment si c'est une idée que nous devrions revoir et discuter .

Le consensus de la réunion de développement et du sprint à SciPy'19 était le suivant: sortons la 1.17.0 et faisons l'expérience du monde réel avant de passer aux prochaines étapes.

vraiment juste se demander si c'est une idée que nous devrions revoir et discuter.

probablement oui, mais dans quelques mois.

probablement oui, mais dans quelques mois.

Ok, merci pour la réponse!

En ce qui concerne le point de copie qui a été soulevé précédemment, je suis curieux de savoir si cela n'est pas résolu par les mécanismes existants. En particulier, qu'en est-il de ces lignes?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Certes, ce serait bien de ramener cela à une ligne. Je suis simplement curieux de savoir si cela fonctionne déjà pour ce cas d'utilisation ou si des éléments nous manquent.

Mon principal problème avec ceci est que cela ne fonctionnerait pas pour les tableaux de canard qui sont immuables, ce qui n'est pas terriblement rare. De plus, pour NumPy, le coût supplémentaire d'allocation d'un tableau, puis de son remplissage, peut être presque nul, mais je ne suis pas sûr que ce soit vrai pour tous les tableaux de canard.

En ce qui concerne le point de copie qui a été soulevé précédemment, je suis curieux de savoir si cela n'est pas résolu par les mécanismes existants. En particulier, qu'en est-il de ces lignes?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Certes, ce serait bien de ramener cela à une ligne. Je suis simplement curieux de savoir si cela fonctionne déjà pour ce cas d'utilisation ou si des éléments nous manquent.

Vous pouvez le faire, mais cela peut nécessiter une logique de copie spéciale (comme dans CuPy cupy / cupy # 2079 ).

Cela dit, une fonction de copie peut être préférable, pour éviter que ce type de code supplémentaire ne soit nécessaire.

D'un autre côté, ce serait une sorte de remplacement de asarray . Je me demandais donc si au lieu d'une nouvelle fonction copy_like , nous voudrions plutôt revoir l' idée suggérée par NEP-18 :

Ceux-ci auront besoin de leurs propres protocoles:
...
array et asarray, car ils sont explicitement destinés à la contrainte sur un objet numpy.ndarray réel.

S'il y a une chance que nous aimerions revoir cela, il vaudrait peut-être mieux commencer un nouveau fil. Des idées, suggestions, objections?

Je ne pense pas que ce soit une bonne idée de changer le comportement de np.array ou np.asarray avec un nouveau protocole. Leur signification établie est de convertir des tableaux NumPy, ce qui explique essentiellement pourquoi nous avons besoin de np.duckarray

Cela dit, nous pourrions envisager d'ajouter un argument like à duckarray . Cela nécessiterait de changer le protocole de la proposition simplifiée ci-dessus - peut-être utiliser __array_function__ au lieu d'un protocole dédié comme __duckarray__ ? Je n'y ai pas vraiment réfléchi.

En ce qui concerne le point de copie qui a été soulevé précédemment, je suis curieux de savoir si cela n'est pas résolu par les mécanismes existants. En particulier, qu'en est-il de ces lignes?

a2 = np.empty_like(a1)
a2[...] = a1[...]

Certes, ce serait bien de ramener cela à une ligne. Je suis simplement curieux de savoir si cela fonctionne déjà pour ce cas d'utilisation ou si des éléments nous manquent.

Mon principal problème avec ceci est que cela ne fonctionnerait pas pour les tableaux de canard qui sont immuables, ce qui n'est pas terriblement rare. De plus, pour NumPy, le coût supplémentaire d'allocation d'un tableau, puis de son remplissage, peut être presque nul, mais je ne suis pas sûr que ce soit vrai pour tous les tableaux de canard.

C'est juste. En fait, nous pouvons déjà simplifier les choses. Par exemple, cela fonctionne avec CuPy et Sparse aujourd'hui.

a2 = np.copy(a1)

C'est juste. En fait, nous pouvons déjà simplifier les choses. Par exemple, cela fonctionne avec CuPy et Sparse aujourd'hui.

a2 = np.copy(a1)

Oui, mais nous voulons aussi "copier ce tableau de canard dans le type de cet autre tableau de canard"

Je ne pense pas que ce soit une bonne idée de changer le comportement de np.array ou np.asarray avec un nouveau protocole. Leur signification établie est de convertir en tableaux NumPy, ce qui explique essentiellement pourquoi nous avons besoin de np.duckarray

Je ne suis pas sûr non plus de cela, et j'étais même réticent à soulever cette question, c'est pourquoi je ne l'avais pas fait jusqu'à aujourd'hui.

Cela dit, nous pourrions envisager d'ajouter un argument similaire à duckarray. Cela nécessiterait de changer le protocole par rapport à la proposition simplifiée ci-dessus - peut-être utiliser __array_function__ au lieu d'un protocole dédié comme __duckarray__? Je n'y ai pas vraiment réfléchi.

Je ne sais pas s'il y aurait des complications avec cela, nous avons probablement besoin d'être prudents, mais j'ai tendance à aimer cette idée. Cela semblerait redondant à différents niveaux, mais peut-être pour suivre le modèle existant, au lieu d'ajouter un paramètre like , nous pourrions avoir duckarray et duckarray_like ?

Oui, mais nous voulons aussi "copier ce tableau de canard dans le type de cet autre tableau de canard"

Que diriez-vous de baser cela autour de np.copyto ?

Que diriez-vous de baser cela autour de np.copyto ?

N'hésitez pas à me corriger si je me trompe, mais je suppose que vous voulez dire quelque chose comme:

np.copyto(cupy_array, numpy_array)

Cela pourrait fonctionner, en supposant que NumPy est prêt à changer le comportement actuel, par exemple, asarray implique toujours que la destination est un tableau NumPy, est-ce que copyto fait la même hypothèse?

np.copyto déjà en charge la répartition avec __array_function__ , mais c'est à peu près équivalent à:

def copyto(dst, src):
    dst[...] = src

Nous voulons l'équivalent de:

def copylike(src, like):
    dst = np.empty_like(like)
    dst[...] = src
    return dst

np.copyto déjà en charge la répartition avec __array_function__ , mais c'est à peu près équivalent à:

def copyto(dst, src):
    dst[...] = src

Nous voulons l'équivalent de:

def copylike(src, like):
    dst = np.empty_like(like)
    dst[...] = src
    return dst

Correct, c'est ce que nous voulons. copyto est distribué et fonctionne si la source et la destination ont le même type, nous avons besoin de quelque chose qui permet la distribution vers la bibliothèque du tableau de destination.

Eh bien, copyto pourrait encore avoir un sens selon la façon dont nous y pensons. Prenons par exemple le cas d'utilisation suivant.

np.copyto(cp.ndarray, np.random.random((3,)))

Cela pourrait se traduire par quelque chose comme allouer et copier les données comme nous l'avons vu. Si nous distribuons environ dst ( cp.ndarray dans ce cas), alors les bibliothèques avec des tableaux immuables pourraient également l'implémenter de manière appropriée. Cela nous évite également d'ajouter une nouvelle API (que NumPy fournit simplement, mais n'utilise pas), ce qui semblait être un problème.

Juste pour faire apparaître une autre pensée qui m'est venue récemment, il vaut la peine de réfléchir à ce que ces API signifieront en aval entre d'autres bibliothèques (par exemple, comment Dask et Xarray interagissent).

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

kevinzhai80 picture kevinzhai80  ·  4Commentaires

keithbriggs picture keithbriggs  ·  3Commentaires

MareinK picture MareinK  ·  3Commentaires

dmvianna picture dmvianna  ·  4Commentaires

inducer picture inducer  ·  3Commentaires