Cookies op Tweakers

Tweakers is onderdeel van DPG Media en maakt gebruik van cookies, JavaScript en vergelijkbare technologie om je onder andere een optimale gebruikerservaring te bieden. Ook kan Tweakers hierdoor het gedrag van bezoekers vastleggen en analyseren. Door gebruik te maken van deze website, of door op 'Cookies accepteren' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt? Bekijk dan ons cookiebeleid.

Meer informatie
Toon posts:

numpy copy optimalisatie

Pagina: 1
Acties:

Vraag


  • htca
  • Registratie: november 2001
  • Laatst online: 18-06 11:29
Mijn vraag
Ik heb een lange 1 dimensional array (lengte > 1.5miljoen) die ik wil opsplitsen in verspringende arrays van lengte 600 en die plaatsen in een matrix. Om een idee te geven:

code:
1
2
3
4
5
6
7
8
9
10
# (lengte 1.5 miljoen of meer)
initial array = [1,2,4,6,4,3,7,8,9,34,47,8,2,....45,2,5,67] 

#matrix n x 600
matrix = [[1, 0, 0, 0,0 ,0, 0,....],
               [2,1,0,0,0,0,0,0,....],
               [4,2,1,0,0,0,0,0,....],
               [6,4,2,1,0,0,0,0,....],
....
]

Op zich kan middels numpy.copy() of rechtstreeks uit de array ([0:600], [1:601], etc even de starts en einde buiten beschouwing gelaten) halen en dat werkt. Maar qua performance duurt dat erg lang. Op zich niet erg, maar wel als je deze exercitie dan ook weer een aantal duizenden keren moet herhalen.
Om een idee te geven, de methode die ik nu gebruik duurt het vullen van de matrix in de orde van 15 tot 20 seconden. De code die ik nu gebruik (snippet):
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        f_load = np.array(F_vector) # de lange vector

        n_location = 600 # locations in the model

        start = 0
        f_matrix = []
        while True:
            f_temp = np.zeros(n_location)
            if start < n_location:
                f_temp[0:start + 1] = f_load[0:start + 1][::-1]
            elif start >= n_location:
                f_temp[n_location-len(f_load[max(0,start-n_location-1):start-1][::-1]):n_location] = f_load[max(0,start-n_location-1):start-1][::-1]
            else:
                f_temp = f_load[max(0,start-n_location-1):start-1][::-1]
            if np.count_nonzero(f_temp) >0:
                f_matrix.append(np.array(f_temp))
            start += 1
            if start > n_location + len(f_load):
                break



Relevante software en hardware die ik gebruik
Ik gebruik python (3.6) en numpy in een pycharm omgeving

Wat ik al gevonden of geprobeerd heb
De oplossing zoals hierboven, maar ik zoek een optimalisatie van deze code.

Alle reacties


  • Gropah
  • Registratie: december 2007
  • Laatst online: 19-06 16:18

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

Waarom gebruik je niet de split functie?

  • AGee
  • Registratie: december 2002
  • Niet online

AGee

Formerly known as naitsoezn

Of reshape. Edit: O wacht, de opdracht is iets complexer :P

[Voor 16% gewijzigd door AGee op 09-07-2020 10:01]

't Het nog nooit, nog nooit zo donker west, of 't wer altied wel weer licht


  • Gropah
  • Registratie: december 2007
  • Laatst online: 19-06 16:18

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

Ah, check, het verspringende gedeelte gemist.

Ik denk dat je best wel wat tijd kunt besparen door de grootte van je matrix van te voren te alloceren. En als je zo vaak 0 in je data hebt kun je wellicht ook kijken naar sparse matrices? Maar wellicht ook handig om uit te leggen wat je wilt bereiken, want ik zou bijna denken dat je het jezelf te moeilijk maakt.

  • htca
  • Registratie: november 2001
  • Laatst online: 18-06 11:29
Gropah schreef op donderdag 9 juli 2020 @ 10:12:
Ah, check, het verspringende gedeelte gemist.

Ik denk dat je best wel wat tijd kunt besparen door de grootte van je matrix van te voren te alloceren. En als je zo vaak 0 in je data hebt kun je wellicht ook kijken naar sparse matrices? Maar wellicht ook handig om uit te leggen wat je wilt bereiken, want ik zou bijna denken dat je het jezelf te moeilijk maakt.
hmmm eens een poging wagen omdat uit te leggen.... (geef gerust aan als het niet duidelijk is)

Ik combineer 2 modellen waarmee superpositie mogelijk is.
In de ene berekening krijg ik als gevolg van een 600 unit belastingen een matrix van 600 x aantal punten (in de orde van 1000).

Uit de exercitie uit de topicstart krijg ik een matrix met x aantal situaties van 600 factoren (elke factor hoort bij een unit belasting) en kost relatief gezien veel tijd, meer dan 2/3 van de loop wordt hier gespendeerd. De lengte van de matrix zou op zich wel uit te rekenen zijn, maar wat ik nu doe is, dat ik eerst een array maak en dan de array toevoeg aan de matrix. Als ik alloceer moet ik de matrix in zijn geheel eerst opzetten (met 0) en dan rechtstreeks vullen denk ik?

Vervolgens loop ik door de matrix met x situaties en vermenigvuldig en tel de uitkomsten op om een verloop te krijgen over de 600 punten (np.matmul voor iedere situatie, wat overigens weer razendsnel gaat). Daarna doe ik de post-processing, figuren bouwen en verdere data analyse.

De matrices zijn niet (echt) sparse.

  • Gropah
  • Registratie: december 2007
  • Laatst online: 19-06 16:18

Gropah

Admin Softe Goederen

Oompa-Loompa 💩

htca schreef op donderdag 9 juli 2020 @ 11:05:
[...]
De lengte van de matrix zou op zich wel uit te rekenen zijn, maar wat ik nu doe is, dat ik eerst een array maak en dan de array toevoeg aan de matrix. Als ik alloceer moet ik de matrix in zijn geheel eerst opzetten (met 0) en dan rechtstreeks vullen denk ik?

[...]
Dat lijkt mij het handigste. Wat ik namelijk denk (maar wellicht handig om te verifieren) dat er gebeurd is dat voor elke array die je toevoegt hij een geheel nieuw stuk geheugen moet alloceren en dat kost redelijk wat tijd, elke keer weer. Dus als je van te voren kunt berekenen hoeveel elementen er in zitten en in 1 keer de ruimte kunt alloceren, bespaar je denk ik veel tijd.

De reden dat ik overigens vroeg naar wat je probeert is omdat met aanvullen met nullen etc je vaak dingen probeert te zoeken. En hoewel array comparisons sneller kunnen, kan het afhankelijk van wat je zoekt ook sneller met dingen zoals tries oid.

[Voor 14% gewijzigd door Gropah op 09-07-2020 11:20]


  • KabouterSuper
  • Registratie: september 2005
  • Niet online
Volgens mij kan je in python wel spelen met lower triangular matrices... tril of tril_indices geeft je hopelijk wat handvatten.

Zoiets?
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
import math

import numpy as np

a=[1,2,3,4,5,6,7,8,9,10]

matrix_size=math.ceil(pow(len(a),1/2))

indices=np.tril_indices(matrix_size)

b=np.zeros(shape=(matrix_size,matrix_size))

b[indices]=a

[Voor 48% gewijzigd door KabouterSuper op 09-07-2020 11:46]


  • htca
  • Registratie: november 2001
  • Laatst online: 18-06 11:29
Gropah schreef op donderdag 9 juli 2020 @ 11:18:
[...]


Dat lijkt mij het handigste. Wat ik namelijk denk (maar wellicht handig om te verifieren) dat er gebeurd is dat voor elke array die je toevoegt hij een geheel nieuw stuk geheugen moet alloceren en dat kost redelijk wat tijd, elke keer weer. Dus als je van te voren kunt berekenen hoeveel elementen er in zitten en in 1 keer de ruimte kunt alloceren, bespaar je denk ik veel tijd.

De reden dat ik overigens vroeg naar wat je probeert is omdat met aanvullen met nullen etc je vaak dingen probeert te zoeken. En hoewel array comparisons sneller kunnen, kan het afhankelijk van wat je zoekt ook sneller met dingen zoals tries oid.
allocatie geeft een snelheidswinst van 2 tot 2.5 ongeveer 8) thanks!
KabouterSuper schreef op donderdag 9 juli 2020 @ 11:34:
Volgens mij kan je in python wel spelen met lower triangular matrices... tril of tril_indices geeft je hopelijk wat handvatten.
Ga ik ook nog even naar kijken!

  • KabouterSuper
  • Registratie: september 2005
  • Niet online
htca schreef op donderdag 9 juli 2020 @ 11:46:
[...]
Ga ik ook nog even naar kijken!
Ik heb een voorbeeldje in mijn vorige post toegevoegd. Die doet niet precies hetzelfde, maar geeft wel aan hoe je met indices kunt spelen.

Om precies te doen wat je wilt, moet je de indices van je list ook handig dupliceren. Hieronder een voorbeeld:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import math

import numpy as np

a=np.array([1.1,2.1,3.1,4.1,5.1,6.1])

matrix_size=len(a)

tri_low_matrix_indices=np.tril_indices(matrix_size)

repeated_indices=tri_low_matrix_indices[0]-tri_low_matrix_indices[1]

b=np.zeros(shape=(matrix_size,matrix_size))

b[tri_low_matrix_indices]=a[repeated_indices]

print(b)

[Voor 90% gewijzigd door KabouterSuper op 09-07-2020 13:12. Reden: Code nog wat efficienter gemaakt]


  • htca
  • Registratie: november 2001
  • Laatst online: 18-06 11:29
KabouterSuper schreef op donderdag 9 juli 2020 @ 11:46:
[...]

Ik heb een voorbeeldje in mijn vorige post toegevoegd. Die doet niet precies hetzelfde, maar geeft wel aan hoe je met indices kunt spelen.

Om precies te doen wat je wilt, moet je de indices van je list ook handig dupliceren. Hieronder een voorbeeld:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import math

import numpy as np

a=np.array([1.1,2.1,3.1,4.1,5.1,6.1])

matrix_size=len(a)

tri_low_matrix_indices=np.tril_indices(matrix_size)

repeated_indices=tri_low_matrix_indices[0]-tri_low_matrix_indices[1]

b=np.zeros(shape=(matrix_size,matrix_size))

b[tri_low_matrix_indices]=a[repeated_indices]

print(b)
Ik ga het weekend eens studeren.... thanks!
Pagina: 1


Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Microsoft Xbox Series X LG CX Google Pixel 5a 5G Sony XH90 / XH92 Samsung Galaxy S21 5G Sony PlayStation 5 Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True