gpt4 book ai didi

sas - PROC DS2 性能问题

转载 作者:行者123 更新时间:2023-12-04 14:14:15 25 4
gpt4 key购买 nike

我试图使用 proc ds2 尝试通过使用多线程功能在正常数据步骤上获得一些性能提升。
fred.testdata 是一个包含 500 万个观测值的 SPDE 数据集。我的代码如下:

proc ds2; 
thread home_claims_thread / overwrite = yes;
/*declare char(10) producttype;
declare char(12) wrknat_clmtype;
declare char(7) claimtypedet;
declare char(1) event_flag;*/
/*declare date week_ending having format date9.;*/
method run();
/*declare char(7) _week_ending;*/
set fred.testdata;
if claim = 'X' then claimtypedet= 'ABC';
else if claim = 'Y' then claimtypedet= 'DEF';
/*_week_ending = COMPRESS(exposmth,'M');
week_ending = to_date(substr(_week_ending,1,4) || '-' || substr(_week_ending,5,2) || '-01');*/
end;
endthread;

data home_claims / overwrite = yes;
declare thread home_claims_thread t;
method run();
set from t threads=8;
end;
enddata;
run;
quit;

我没有包括所有的 IF 语句,只包括了一些,否则它会占用几页(你应该希望得到这个想法)。由于代码目前的运行速度比正常的数据步骤快得多,但是当发生以下任何一种情况时,会出现严重的性能问题:
  • 我取消注释任何声明语句
  • 我在 fred.testdata 中包含任何数字变量(即使没有对数字变量执行任何计算)

  • 我的问题是:
  • 有没有什么方法可以将数值变量引入 fred.testdata 中而不会出现明显的减速,这使得 DS2 比正常数据步骤慢? (对于这个包含数字列/秒的 500 万行的小表,ds2 的实时时间约为 1 分 30,正常数据步骤的时间约为 20 秒)。实际的全表接近 6 亿行。例如,我希望能够在不引入 5 倍运行时间性能损失的情况下进行周结束转换。 ds2 WITHOUT 声明语句和数字变量的运行时间大约需要 7 秒
  • 有什么方法可以压缩 ds2 中的表,而无需执行额外的数据步骤来压缩它?

  • 谢谢

    最佳答案

    两种方法尝试:使用proc hpds2让 SAS 处理并行执行,或更手动的方法。请注意,使用这两种方法中的任何一种都不可能始终保持顺序。

    方法一:PROC HPDS2

    HPDS2是一种对数据进行大规模并行处理的方式。在单机模式下,它将每个内核并行运行,然后将所有数据重新组合在一起。您只需对代码稍作修改即可运行。
    hpds2有一个设置,您可以在 data 中声明您的数据和 out proc 中的声明陈述。您的 dataset语句将始终使用以下语法:

        data DS2GTF.out;
    method run();
    set DS2GTF.in;
    <code>;
    end;
    enddata;

    知道了这一点,我们可以修改您的代码以在 HPDS2 上运行:
    proc hpds2 data=fred.test_data
    out=home_claims;

    data DS2GTF.out;
    /*declare char(10) producttype;
    declare char(12) wrknat_clmtype;
    declare char(7) claimtypedet;
    declare char(1) event_flag;*/

    /*declare date week_ending having format date9.;*/
    method run();

    /*declare char(7) _week_ending;*/
    set DS2GTF.in;

    if claim = 'X' then claimtypedet= 'ABC';
    else if claim = 'Y' then claimtypedet= 'DEF';

    /*_week_ending = COMPRESS(exposmth,'M');
    week_ending = to_date(substr(_week_ending,1,4) || '-' || substr(_week_ending,5,2) || '-01');*/

    end;
    enddata;

    run;
    quit;

    方法二:使用rsubmit分割数据并追加

    下面的代码使用了 rsubmit并直接观察访问以分块读取数据,然后在最后将它们全部附加在一起。如果您为 Block I/O 设置了数据,这个方法会特别好用。
    options sascmd='!sascmd'
    autosignon=yes
    noconnectwait
    noconnectpersist
    ;

    %let cpucount = %sysfunc(getoption(cpucount));

    %macro parallel_execute(data=, out=, threads=&cpucount);

    /* Get total obs from data */
    %let dsid = %sysfunc(open(&data.));
    %let n = %sysfunc(attrn(&dsid., nlobs));
    %let rc = %sysfunc(close(&dsid.));

    /* Run &threads rsubmit sessions */
    %do i = 1 %to &threads;

    /* Determine the records that each worker will read */
    %let firstobs = %sysevalf(&n.-(&n./&threads.)*(&threads.-&i+1)+1, floor);
    %let lastobs = %sysevalf(&n.-(&n./&threads.)*(&threads.-&i.), floor);

    /* Get this session's work directory */
    %let workdir = %sysfunc(getoption(work));

    /* Send all macro variables to the remote session, and simultaneously start the remote session */
    %syslput _USER_ / remote=worker&i.;

    /* Check for an input libname */
    %if(%scan(&data., 2, .) NE) %then %do;
    %let inlib = %scan(&data., 1, .);
    %let indsn = %scan(&data., 2, .);
    %end;
    %else %do;
    %let inlib = workdir;
    %let indsn = &data.;
    %end;

    /* Check for an output libname */
    %if(%scan(&out., 2, .) NE) %then %do;
    %let outlib = %scan(&out., 1, .);
    %let outdsn = %scan(&out., 2, .);
    %end;
    %else %do;
    %let outlib = workdir;
    %let outdsn = &out.;
    %end;

    /* Work library location of this session to be inherited by the parallel session */
    %let workdir = %sysfunc(getoption(work));

    /* Sign on to a remote session and send over all user-made macro variables */
    %syslput _USER_ / remote=worker&i.;

    /* Run code on remote session &i */
    rsubmit remote=worker&i. inheritlib=(&inlib.);

    libname workdir "&workdir.";

    data workdir._&outdsn._&i.;
    set &inlib..&indsn.(firstobs=&firstobs. obs=&lastobs.);
    /* <PUT CODE HERE>;*/
    run;
    endrsubmit;

    %end;

    /* Wait for everything to complete */
    waitfor _ALL_;

    /* Append all of the chunks together */
    proc datasets nolist;
    delete &out.;

    %do i = 1 %to &threads.;
    append base=&out.
    data=_&outdsn._&i.
    force
    ;
    %end;

    /* Optional: remove all temporary data */
    /* delete _&outdsn._:;*/
    quit;

    libname workdir clear;
    %mend;

    您可以使用以下代码测试其功能:
    data pricedata;
    set sashelp.pricedata;
    run;

    %parallel_execute(data=pricedata, out=test, threads=3);

    如果您查看 WORK 目录中的临时文件,您会看到它在 3 个并行进程之间平均拆分数据集,并且它加起来等于原始总数。
    _test_1 = 340
    _test_2 = 340
    _test_3 = 340
    TOTAL = 1020

    pricedata = 1020

    关于sas - PROC DS2 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47522561/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com