Профилирование памяти с помощью data.table - PullRequest
6 голосов
/ 08 октября 2019

Какой правильный способ профилировать память в коде R, который содержит вызовы функций data.table? Допустим, я хочу определить максимальное использование памяти во время выражения.

Эта ссылка указывает на то, что Rprofmem может быть неправильным выбором: https://cran.r -project.org / web / packages / profmem/vignettes/profmem.html

Все выделения памяти, которые выполняются с помощью встроенной части allocVector3 () собственного API R, регистрируются, что означает, что регистрируются почти все выделения памяти. Любые объекты, размещенные таким образом, автоматически освобождаются сборщиком мусора R в какой-то момент. События сборки мусора не регистрируются profmem (). Не регистрируемые распределения - это те, которые сделаны не родными библиотеками R или пакетами R, которые используют собственный код Calloc () / Free () для внутренних объектов. Такие объекты не обрабатываются сборщиком мусора R.

Исходный код data.table содержит множество вызовов к Calloc() и malloc(), поэтому это говорит о том, что Rprofmem не будет измерять всю памятьраспределены по data.table функциям. Если Rprofmem не правильный инструмент, почему Мэтью Доул использует его здесь: R: перебрать столбцы в data.table ?

Я нашел ссылку, предлагающую похожие потенциальные проблемы для gc() (которая может использоваться для измерения максимального использования памяти между двумя вызовами gc()): https://r.789695.n4.nabble.com/Determining-the-maximum-memory-usage-of-a-function-td4669977.html

gc () - хорошее начало. Вызовите gc (reset = TRUE) перед и gc () после вашей задачи, и вы увидите максимальный объем дополнительной памяти, используемый R в промежуточный период. (Это не относится к памяти, неправильно распределенной скомпилированным кодом, которую гораздо сложнее измерить, поскольку она используется повторно.)

Ничего из того, что я обнаружил, не предполагает, что подобные проблемы существуют с Rprof(memory.profiling=TRUE). Означает ли это, что подход Rprof будет работать для data.table, даже если он не всегда использует R API для выделения памяти?

Если Rprof(memory.profiling=TRUE) на самом деле не является подходящим инструментом для работы, что такое?

Будет ли ssh.utils::mem.usage работать?

Ответы [ 2 ]

2 голосов
/ 12 октября 2019

Это не относится к data.table. Недавно в твиттере шла дискуссия о том же поведении dplyr: https://mobile.twitter.com/healthandstats/status/1182840075001819136

/usr/bin/time -v Rscript -e 'library(data.table); CJ(1:1e4, 1:1e4)' |& grep resident

Также есть интересный проект cgmemtime , но он требует немного больше настроек.

Если вы используете Windows, я предлагаю вам перейти на Linux.

0 голосов
/ 09 октября 2019

Если вы используете Windows, вы можете вызывать память Powershell и другие объекты производительности для RGui и сжатия памяти как системные команды через R и вызывать различные счетчики памяти. У меня пока нет пути для хранения объектов Powershell в R. Код Powershell для RGui и «Сжатие памяти», используемый Windows для хранения часто используемых объектов:

    $t1 = ps | where {$_.Name -EQ 'RGui' -or $_.Name -EQ 'Memory Compression'};
    $t2 = $t1 | Select { $_.Id;
    [math]::Round($_.WorkingSet64/1MB);
    [math]::Round($_.PrivateMemorySize64/1MB);
    [math]::Round($_.VirtualMemorySize64/1MB) };
    $t2 | ft * 

    $t1 | gm -View All
    $t1.Modules
    $t1.MaxWorkingSet

Встроенный в R Powershell:

    ps_f <- function() { system("powershell -ExecutionPolicy Bypass -command $t1 = ps | where {$_.Name -EQ 'RGui' -or $_.Name -EQ 'Memory Compression'};
    $t2 = $t1 | Select { 
     $_.Id;
     [math]::Round($_.WorkingSet64/1MB);
     [math]::Round($_.PrivateMemorySize64/1MB);
     [math]::Round($_.VirtualMemorySize64/1MB) };
    $t2 | ft * "); }

    ps_f()

     $_.Id;                                                                                                                
     [math]::Round($_.WorkingSet64/1MB);                                                                                   
     [math]::Round($_.PrivateMemorySize64/1MB);                                                                            
     [math]::Round($_.VirtualMemorySize64/1MB)                                                                             
    -----------------------------------------------------------------------------------------------------------------------
    {2264, 1076, 3, 1401}                                                                                                  
    {15832, 3544, 6691, 11965}   



    ps_mem <- function() { system("powershell -ExecutionPolicy Bypass -command $t1 = ps | where {$_.Name -EQ 'RGui' -or $_.Name -EQ 'Memory Compression'};
    $t1 | Select ProcessName,MaxWorkingSet,MinWorkingSet,PagedMemorySize64,NonpagedSystemMemorySize64;")} 

    > ps_mem()

    ProcessName                : Memory Compression
    MaxWorkingSet              : 
    MinWorkingSet              : 
    PagedMemorySize64          : 3411968
    NonpagedSystemMemorySize64 : 0

    ProcessName                : Rgui
    MaxWorkingSet              : 1413120
    MinWorkingSet              : 204800
    PagedMemorySize64          : 7014719488
    NonpagedSystemMemorySize64 : 6662736

    # run some data.table operation

    > ps_mem()
    ProcessName                : Memory Compression
    MaxWorkingSet              : 
    MinWorkingSet              : 
    PagedMemorySize64          : 3411968
    NonpagedSystemMemorySize64 : 0

    ProcessName                : Rgui
    MaxWorkingSet              : 1413120
    MinWorkingSet              : 204800
    PagedMemorySize64          : 7015915520
    NonpagedSystemMemorySize64 : 6662736

Код Powershell:

    $t1 | where {$_.ProcessName -eq "Rgui"} | Measure-Object -Maximum *memory* | ft  Property,Maximum

Powershell, встроенный в R:

    ps_mem_ <- function() { system("powershell -ExecutionPolicy Bypass -command $t1 = ps | where {$_.Name -EQ 'RGui' -or $_.Name -EQ 'Memory Compression'};
    $t2 = $t1 | where {$_.ProcessName -eq 'Rgui'}; 
    $t2 | Measure-Object -Maximum *memory* | ft  Property,Maximum ")} 

    # having some problems with rollover...

    > ps_mem_()

    Property                       Maximum
    --------                       -------
    NonpagedSystemMemorySize       6662736
    NonpagedSystemMemorySize64     6662736
    PagedMemorySize            -1570734080
    PagedMemorySize64           7019200512
    PagedSystemMemorySize           680240
    PagedSystemMemorySize64         680240
    PeakPagedMemorySize        -1260961792
    PeakPagedMemorySize64      11623940096
    PeakVirtualMemorySize       -161009664
    PeakVirtualMemorySize64    17018859520
    PrivateMemorySize          -1570734080
    PrivateMemorySize64         7019200512
    VirtualMemorySize           -339103744
    VirtualMemorySize64        12545798144

    some data.table run

    > ps_mem_()

    Property                       Maximum
    --------                       -------
    NonpagedSystemMemorySize       6662736
    NonpagedSystemMemorySize64     6662736
    PagedMemorySize            -1570734080
    PagedMemorySize64           7019200512
    PagedSystemMemorySize           680240
    PagedSystemMemorySize64         680240
    PeakPagedMemorySize        -1260961792
    PeakPagedMemorySize64      11623940096
    PeakVirtualMemorySize       -161009664
    PeakVirtualMemorySize64    17018859520
    PrivateMemorySize          -1570734080
    PrivateMemorySize64         7019200512
    VirtualMemorySize           -339103744
    VirtualMemorySize64        12545798144

Чтобы увидеть все объекты Rgui:

    $t1 | gm -View All


       TypeName: System.Diagnostics.Process

    Name                       MemberType     Definition
    ----                       ----------     ----------
    Handles                    AliasProperty  Handles = Handlecount
    Name                       AliasProperty  Name = ProcessName
    NPM                        AliasProperty  NPM = NonpagedSystemMemorySize64
    PM                         AliasProperty  PM = PagedMemorySize64
    SI                         AliasProperty  SI = SessionId
    VM                         AliasProperty  VM = VirtualMemorySize64
    WS                         AliasProperty  WS = WorkingSet64
    Disposed                   Event          System.EventHandler Disposed(System.Object, System.EventArgs)
    ErrorDataReceived          Event          System.Diagnostics.DataReceivedEventHandler ErrorDataReceived(System.Object, System.Diagnostics.DataReceivedEventArgs)
    ...
...