Avatar
hanpari
Redaktor
Avatar
hanpari:

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
Filip Šohajek
Redaktor
Avatar
Odpovídá na hanpari
Filip Šohajek:

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
Avatar
gcx11
Redaktor
Avatar
Odpovídá na hanpari
gcx11:

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
Redaktor
Avatar
Odpovídá na hanpari
coells:

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

 
Nahoru Odpovědět 18.6.2014 22:03
Avatar
hanpari
Redaktor
Avatar
hanpari:

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
Redaktor
Avatar
hanpari:

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
Redaktor
Avatar
hanpari:

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.