Sas 进程DS2性能问题

Sas 进程DS2性能问题,sas,sas-ds2,Sas,Sas Ds2,我试图使用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;

我试图使用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语句,只包括了一些,否则它会占用几页(你应该有希望得到这个想法)。根据目前的代码,它的工作速度比正常的数据步骤快很多,但是当出现以下情况时,会出现严重的性能问题:

  • 我取消对任何declare语句的注释
  • 我在fred.testdata中包含任何数值变量(即使没有对数值变量执行任何计算)
  • 我的问题是:

  • 有没有办法在fred.testdata中引入数值变量,而不会导致DS2比正常数据步骤慢很多?(对于这个包含500万行(包括数字列/s)的小表格,ds2的实时时间约为1分30秒,而正常数据步长的实时时间约为20秒)。实际的完整表接近6亿行。例如,我希望能够在不引入5倍运行时性能损失的情况下进行周末转换。没有declare语句和数字变量的ds2的运行时间约为7秒
  • 是否有任何方法可以在ds2中压缩表,而不必执行额外的数据压缩步骤

  • 谢谢您

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

    方法1:PROC HPDS2

    是执行大规模数据并行处理的一种方式。在单机模式下,它将对每个内核进行并行运行,然后将所有数据放回一起。您只需要对代码做一些轻微的修改就可以运行它

    hpds2
    有一个设置,您可以在
    data
    中声明数据,在
    proc
    语句中声明
    out
    语句。
    data
    set
    语句将始终使用以下语法:

        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;
    
    方法2:使用rsubit和append拆分数据

    下面的代码使用
    rsubmit
    和直接观察访问来读取数据块,然后在末尾将它们全部附加在一起。如果您已将数据设置为

    如果您查看工作目录中的临时文件,您将看到它在3个并行进程中均匀地分割数据集,并将其相加为原始总数

    _test_1 = 340
    _test_2 = 340
    _test_3 = 340
    TOTAL   = 1020
    
    pricedata = 1020
    

    使用Proc HPds2是否可行?(通常HP版本效率更高。)您是否尝试过先将新的空字段添加到fred.testdata(alter table…),然后通过proc sql update更新它?有这么大的一张桌子,你似乎被I/O束缚住了。要添加的现有列和新列的数量是多少?主要问题是DS2中的线程使用单个读卡器,而不是多个并行读卡器。HPDS2可能能够做到这一点。我过去使用过一种变通方法,涉及RSubit和多个SAS会话,以并行块的形式读取数据。这是一种什么样的SAS设备?网格、服务器、桌面还是CAS/Viya?当你说它存储在SPDE中时,是SPDE存储在一组分布式磁盘上,还是SPDE存储在一个磁盘上?谢谢大家的评论。我认为第二个答案是正确的(从简单性和有效性的角度来看),尽管HPDS2的答案很有趣。谢谢Stu的建议。我本想使用rsubmit,但不幸的是我们没有SAS CONNECT许可证。好的,我已经尝试测试hpds2,下面是我的发现。它输出所需的结果(+我可以看到所有8个内核的利用率都在70%左右),但性能比正常的数据步骤慢。以下是一些统计数据(这没有引入数值变量,因此我预计一旦引入它们,性能会下降):使用hpds2运行53秒实时,使用proc ds2运行8秒实时,18秒使用普通数据步骤我非常喜欢hpds2,因为它的编码有点简单,但不幸的是,它似乎比proc ds2慢得多,即使它使用多个Core。在这种情况下,您可能需要进行一些额外的性能监控,以查看瓶颈可能在哪里。使用
    options msglevel=i
    帮助诊断流程中最慢的部分。关于性能优化的良好白皮书可以在这里找到:ETL性能:如果您看到实时性远远大于CPU时间,那么可能的瓶颈在于磁盘I/O。调整
    bufno
    、将所选列减少到所需的数量以及减小列大小等都会有很大帮助。options msglevel=I(或N)似乎对我日志中的内容没有任何影响。下面是我得到的全部(注意,在正常的数据步骤中,实时时间和CPU时间几乎完全相等,这就是为什么我尝试沿着这个多线程路径):注意:HPDS2过程是在单机模式下执行的。注:从数据集FRED.TEST_数据中读取了5000000个观察值。注:数据集WORK.HOME_索赔_HPDS2有5000000个观察值和182个变量。注:使用的程序HPDS2(总处理时间):实时51.21秒cpu时间2:51.80
    data pricedata;
        set sashelp.pricedata;
    run;
    
    %parallel_execute(data=pricedata, out=test, threads=3);
    
    _test_1 = 340
    _test_2 = 340
    _test_3 = 340
    TOTAL   = 1020
    
    pricedata = 1020