GAP Message - remark #30753: (DTRANS) Convert array of struct ... into a new struct ...

Message

Convert array of struct "str" into a new struct whose fields are arrays of the corresponding fields in the original struct. This improves performance due to better data locality. [VERIFY] Make sure that the restructured code satisfies the original program semantics.
This message applies to C/C++ only

Description

You should apply full peeling to a class or structure. This is done by splitting a class or structure into separate fields. This should improve performance by better utilizing the processor cache. This message is generated only when the entire application is built with Interprocedural Optimization (IPO). This transformation requires that you change all access to any peeled structure and its fields in the entire application. In some cases, it may not be easy to change source code to apply full peeling.

Let us assume we want to apply full peeling for the following structure and its references:

struct {
  int a;
  double b;
} S, *sp;

struct S s_arr[N];
...
sp = calloc(N, sizeof(S)); // Allocate memory
 
 ...sp[i].a ...              // Access "a" field from "sp"
 ...sp[i].b ...              // Access "b" field from "sp"
 ...s_arr[i].a ...              // Access "a" field from "s_arr"
 ...s_arr[i].b ...              // Access "b" field from "s_arr"

They can be transformed as follows to apply full peeling to structure

struct {
 int a;
} s1;

struct {
 double b;
} new_b, *sp_b;

struct S s_arr[N];
struct new_b s_arr_b[N];
...
sp = calloc(N, sizeof(s1));  // Allocate memory for all peeled fields
sp_b = calloc(N, sizeof(new_b)); 
...
s_arr[i].a                      // Access "a" field from "s_arr"
s_arr_b[i].b                    // Access "b" field from "s_arr_b"
sp[i].a                         // Access "a" field from original pointer "sp"
sp_b[i].b                       // Access "b" field from new pointer "sp_b"
.. 

Example

// peel.c
#include <stdio.h>
#include <stdlib.h>

#define N 100000
int a[N];
double b[N];
struct S3 {
    int *pi;
    double d;
    int j;
};


struct S3 *sp;

void init_hot_s3_i()
{

    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp[ii].pi = &a[ii];
    }
}
void init_hot_s3_d()
{
    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp[ii].d = b[ii];
    }
}
void init_hot_s3_j()
{
    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp[ii].j = 0;
    }
}
void dump_s3()
{
    int ii;

    for (ii = 0; ii < N; ii++) {
        printf("i= %d ", *(sp[ii].pi));
        printf("d= %g n", sp[ii].d);
        printf("j= %g n", sp[ii].j);
    }
}

main()
{

   sp = (struct S3 *)calloc(N, sizeof(struct S3));
   init_hot_s3_i();
   init_hot_s3_d();
   init_hot_s3_j();
   dump_s3();
}

For the above example, the compiler generates the following advice on x86win with
'icl -Qguide=4 -Qipo peel.c'

 

peel.c(7): remark #30753: (DTRANS) Convert array of struct "S3" into a new struct whose fields are arrays of the corresponding fields in the original struct. This improves performance due to better data locality. [VERIFY] Make sure that the restructured code satisfies the original program semantics.

 

For the above example, sources can be modified as follows to apply full peeling as suggested.

#include <stdio.h>
#include <stdlib.h>

#define N 100000
int a[N];
double b[N];
struct S3 {
    int *pi;
};

struct new_d {
    double d;
};

struct new_j {
    int j;
};


struct S3 *sp;
struct new_d *sp_d;
struct new_j *sp_j;

void init_hot_s3_i()
{

    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp[ii].pi = &a[ii];
    }
}
void init_hot_s3_d()
{
    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp_d[ii].d = b[ii];
    }
}
void init_hot_s3_j()
{
    int ii = 0;

    for (ii = 0; ii < N; ii++) {
        sp_j[ii].j = 0;
    }
}
void dump_s3()
{
    int ii;

    for (ii = 0; ii < N; ii++) {
        printf("i= %d ", *(sp[ii].pi));
        printf("d= %g n", sp_d[ii].d);
        printf("j= %g n", sp_j[ii].j);
    }
}

main()
{

   sp = (struct S3 *)calloc(N, sizeof(struct S3));
   sp_d = (struct new_d *)calloc(N, sizeof(struct new_d));
   sp_j = (struct new_j *)calloc(N, sizeof(struct new_j));
   init_hot_s3_i();
   init_hot_s3_d();
   init_hot_s3_j();
   dump_s3();
}

Optimization Notice in English

Per informazioni più dettagliate sulle ottimizzazioni basate su compilatore, vedere il nostro Avviso sull'ottimizzazione.
Contrassegni: