Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
hanpari
Tvůrce
Avatar
hanpari:18.6.2014 20:29

Ahoj všichni,

při práci se Solidworksem (3d CAD) jsem si všiml, že i v případech, že procesor nebo paměť nejsou plně vytížené, dochází k tomu, že se program "kousne". Co se týče procesor, tam asi hraje roli optimalizace pro víc vláken, nicméně jsem několikrát při práci s náročnými programy sledoval jejich spotřebu paměti. Kupodivu se nikdy nepřehouply přes 2-3 GB (mluvím přirozeně o 64 bitovém systému s 8 GB RAM).

Proto jsem se rozhodl, že zkusím pomocí pythonu vytížit svou paměť na maximum. Stručně řečeno, nepovedlo se. Tady je výstup z mých neúspěšných pokusů, které skončily sice peakem v paměti o cca 0,5 GB, ale python následně vyhlásil MemoryError:

>>> s=[1 for i in range(2**100)]
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    s=[1 for i in range(2**100)]
  File "<pyshell#14>", line 1, in <listcomp>
    s=[1 for i in range(2**100)]
MemoryError
>>> s
>>> s=[1 for i in range(2**20)]
>>> s1=s[:]
>>> s1=[s[:] for i in range(2**10)]
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    s1=[s[:] for i in range(2**10)]
  File "<pyshell#18>", line 1, in <listcomp>
    s1=[s[:] for i in range(2**10)]
MemoryError
>>> s1=[s[:] for i in range(100)]
>>> s2=[s[:] for i in range(100)]
>>> s3= [s2[:] for i in range(5)]
>>> s3=s1[:]
>>> s3= [s2[:] for i in range(5)]
>>> s3= [s2[:] for i in range(100)]
>>> len(s2)
100
>>> s3= [s2[:] for i in range(100)]
>>> s=[1 for i in range(2**20)]
>>> s2=[s[:] for i in range(1000)]
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    s2=[s[:] for i in range(1000)]
  File "<pyshell#28>", line 1, in <listcomp>
    s2=[s[:] for i in range(1000)]
MemoryError

Jak je vidět, pokoušel jsem se vytvářet pole polí, abych nevyvolal výjimku MemoryError, ale k ničemu to nevedlo. Vše jsem sledoval Správě úloh >> Výkon (systém Win8).

Tady jsou mé dvě otázky:

1/ Jakým elegantním způsobem vytížit paměť, pokud to vůbec jde?

2/ Lze zjistit, kolik zabírá proměnná místa v paměti, ekvivalent céčkovského sizeof.

PS: Bod 2 jsem si nakonec vygooglil :)

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48
Editováno 18.6.2014 20:31
 
Odpovědět
18.6.2014 20:29
Avatar
Odpovídá na hanpari
Neaktivní uživatel:18.6.2014 21:30

Mělo by fungovat načtení nějakého velkého souboru do proměnné, ale řeknu ti, že na tyto věci se spíše hodí nízkoúrovňové jazyky, které ti dovolí alokovat klidně 5GB na jednom řádku :)

//EDIT:Tak ani to načítání nepůjde. Python má prostě určité limity.

Editováno 18.6.2014 21:31
Nahoru Odpovědět
18.6.2014 21:30
Neaktivní uživatelský účet
Avatar
gcx11
Tvůrce
Avatar
Odpovídá na hanpari
gcx11:18.6.2014 21:51

A co takhle nekonečná rekurze?

Vytvoříš rekurzivní funkci a nastavíš hodně velkou maximální rekurzi pomocí modulu sys a funkce:

sys.setrecursionlimit()

Ještě mě napadlo:

except MemoryError: pass

Ale to bych raději nezkoušel...

 
Nahoru Odpovědět
18.6.2014 21:51
Avatar
coells
Tvůrce
Avatar
Odpovídá na hanpari
coells:18.6.2014 22:03

Nainstaluj si Sharepoint, spolehlivě zaplní celou paměť.

 
Nahoru Odpovědět
18.6.2014 22:03
Avatar
hanpari
Tvůrce
Avatar
hanpari:18.6.2014 22:13

Díky všem za radu. Trochu jsem se inspiroval a podařilo se mi dostat na skoro 4 GB.

Pomocí tohoto:

>>> d=[2]
>>> import sys
>>> def vypln(pocet):
        for i in range(pocet):
                d.append(d[:])
        print(sys.getsizeof(d))

Spolehlive spadne vypln(10 na 5) 10 na 4 ještě utáhne. Zítra zkusím použít víc seznamů, místo jednoho d :)

Editováno 18.6.2014 22:14
 
Nahoru Odpovědět
18.6.2014 22:13
Avatar
hanpari
Tvůrce
Avatar
hanpari:19.6.2014 9:27

Takže záhada vyřešena. Omlouvám se všem.
Můj python běží jako 32-bitová aplikace.
Tím pádem se zarazil o 4 GB strop.

 
Nahoru Odpovědět
19.6.2014 9:27
Avatar
hanpari
Tvůrce
Avatar
hanpari:19.6.2014 15:17

Udělal jsem si takovou jednoduchou třídu. Její použití je myslím jasné. Kdyby někdo chtěl experimentovat :)

from sys import getsizeof
class MemoryFiller():
    def __init__(self, megabytes = 1):
        KB = []
        while getsizeof(KB) <= 1024:
            KB.append(True)
        self._megabytes = [KB[:]
                           for i in range(1024 * megabytes)]

if __name__ == "__main__":
    # zabere cca 6 GB paměti.
    mf = MemoryFiller(6000)
Editováno 19.6.2014 15:18
 
Nahoru Odpovědět
19.6.2014 15:17
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.