Кэш процессора является недействительным в программировании на C?

это программа на C под Linux / GUN:

#include<stdio.h>
#include<sys/time.h>
#define Max 1024*1024

int main()
{
struct timeval start,end;
long int dis;
int i;
int m=0;
int a[Max];
gettimeofday(&start,NULL);
for(i=0;i<Max;i += 1){
a[Max] *= 3;
}
gettimeofday(&end,NULL);
dis = end.tv_usec - start.tv_usec;
printf("time1: %ld\n",dis);

gettimeofday(&start,NULL);
for(i=0;i<Max;i += 16){
a[Max] *= 3;
}
gettimeofday(&end,NULL);
dis = end.tv_usec - start.tv_usec;
printf("time2: %ld\n",dis);

return 0;
}

выход:

время1: 7074

время2: 234

это большое расстояние

эта программа на Java:

public class Cache1 {
public static void main(String[] args){
int a[] = new int[1024*1024*64];

long  time1 = System.currentTimeMillis();
for(int i=0;i<a.length;i++){
a[i] *= 3;
}
long time2 = System.currentTimeMillis();
System.out.println(time2 - time1);

time1 = System.currentTimeMillis();
for(int i=0;i<a.length;i += 16){
a[i] *= 3;
}
time2 = System.currentTimeMillis();
System.out.println(time2 - time1);
}
}

выход:

92

82

это то же самое

с кешем процессора. почему они имеют такую ​​разницу? кэш процессора недопустим в программировании на C?

2

Решение

Я надеюсь, вы понимаете, что разница в единицах времени в этих тестах составляет 10 ^ 3. Код на C на порядок быстрее, чем код Java.

В коде C должно быть a[i] вместо a[Max],

Что касается кеша: поскольку вы обращаетесь только к одной ячейке памяти в вашем C-коде (что вызывает неопределенное поведение), ваш C-тест полностью недействителен.

И даже если бы это было правильно, ваш метод несовершенен. Вполне возможно, что операции умножения и даже целые циклы были полностью пропущены C-компилятором, так как от их результата ничего не зависит.

Ожидается результат, когда первый запуск занимает много времени, а второй — меньше времени. В любом случае данные должны быть загружены в кэш, и это требует времени. После загрузки операции с этими данными занимают меньше времени.

Java может либо вообще не использовать кеш (маловероятно), либо предварительно загружать весь массив в кеш даже перед выполнением циклов. Это объясняет равные сроки исполнения.

4

Другие решения

У вас есть три размера кэша, это обычно

  • L1: 32 КБ (данные), 4 такта
  • L2: 256 КБ, 10-11 тактов
  • L3: 3-24 МБ. 40 — 75 тактов.

Все, что больше этого, не помещается в кеш, как будто вы просто прокручиваете память, как будто их там нет.

Я предлагаю вам написать тест, который эмпирически определяет размеры кэша ЦП, как хорошее упражнение, чтобы помочь вам понять это. Кстати, вам не нужно использовать *= осуществлять кэш, как это упражнение ALU. Возможно, есть более простая операция, которую вы можете использовать;)

В случае вашего Java-кода, скорее всего, он еще не скомпилирован, поэтому вы видите скорость взаимодействия, а не доступ к памяти.

Я предлагаю вам повторно запустить тест на меньших объемах памяти в течение как минимум 2 секунд и взять среднее значение.

2

По вопросам рекламы [email protected]