CAS

CAS vs. SAS: Understanding the Performance and Behavior Differences of the Data Step

Simon 24/08/2022 4 vistas

When transitioning to SAS© Viya, a common question among developers is: why does some code seem much faster in CAS, while in other cases the gain is less obvious? More importantly, why do certain logical codes, which worked perfectly in SAS© 9, produce different results in CAS?

This article explores the underlying mechanisms that distinguish the traditional SAS© engine (SMP) from the distributed CAS engine (MPP), focusing on the DATA step.

1. Speed: In-Memory and Disk I/O

One of the most obvious advantages of CAS is in-memory processing.

  • Classic SAS© (SAS© 9): Processing often involves reading and writing to the hard disk. Even if the processor is fast, the bottleneck is usually the writing stage (I/O).

  • CAS: Data resides in RAM. Eliminating disk writing steps significantly speeds up overall execution time.

This often explains why code that generates large volumes of data (like a loop creating millions of lines with calculations) runs faster in CAS: the time saved comes not just from the CPU calculation, but from the absence of physical disk writing.

2. The "Single Thread" Trap

However, it is crucial to note that CAS is not magic. Not everything runs automatically in parallel.

Let's take the example of a DATA step that generates data without an input table (e.g., a DO loop from 1 to 5 million to create simulated data):

1/* Exemple de génération sans entrée */
2DATA casuser.simulation;
3 DO i=1 to 5000000;
4 /* calculs complexes */
5 OUTPUT;
6 END;
7RUN;

In this specific case, CAS will run this code on a single thread. The log will display an explicit note:

NOTE: The DATA step has no input data set and will run in a single thread.

In a purely single-threaded scenario, the classic SAS© 9 engine is sometimes more efficient and even faster than CAS, as it has less system management "overhead" than the distributed engine. The power of CAS lies in distribution; without distribution, this gain can be nullified.

3. The Paradigm Shift: Parallelism and Partitioning

The real architectural difference appears when the DATA step reads a distributed table. CAS divides the data into blocks and distributes them among several threads (and potentially several nodes/machines).

This introduces significant behavioral changes for some historic SAS© instructions.

The case of RETAIN

In SAS© 9, the RETAIN statement holds a value from one observation to the next. In CAS, this retention is done within the same thread. A value retained in "Thread 1" is not visible to "Thread 2".

The trap of END=EOF

This is arguably the most common pitfall. In classic SAS©, the if eof; condition triggers only once, at the end of the table.

In a distributed (multi-threaded) environment, the logic changes:

  • Each thread processes its part of the data.

  • Each thread has its own end-of-file indicator.

If you run this code in CAS with multiple threads:

1DATA casuser.resultat;
2 SET casuser.SOURCE END=eof;
3 IF eof;
4 /* Somme cumulative ou autre logique de fin */
5RUN;

You will not get a single line, but as many lines as there are active threads. If your session uses 36 threads, you will have 36 output observations, each representing the last line processed by that specific thread.

To get a global total, an additional aggregation step (post-processing) is often necessary.

4. Function Compatibility

Finally, when migrating code, you must keep in mind that not all SAS© functions are implemented in CAS. If a function is not natively supported by the CAS engine, the system can sometimes transfer the data to the Compute Server to perform the processing, which nullifies the performance benefits of distributed processing. It is recommended to consult the documentation to ensure that the functions used are "CAS-enabled".

The transition from SAS© 9 to CAS is not just about changing the LIBNAME.

  • For performance: CAS excels at massive in-memory and parallel processing, but can be less efficient for small volumes or purely sequential (single-threaded) tasks.

  • For logic: Developers must adapt their "mental map." The concept of sequential reading of a single file from beginning to end disappears in favor of independent block processing.