2012-06-30 2 views
6

Я пишу программу C, в которой мне нужно очистить память. Я хотел бы знать, есть ли какая-либо системная команда UNIX для очистки кеша процессора.Как очистить кеш процессора в Linux от программы C?

Это требование для моего проекта, который включает в себя расчет времени, затраченного на мою логику.

Я прочитал о функции cacheflush(char *s, int a, int b), но я не уверен, будет ли он подходящим и что передать в параметрах.

+3

Почему вы * необходимости * очистить кэш? –

+0

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

+0

Возможный дубликат http://stackoverflow.com/questions/1756825/cpu-cache-flush – Tudor

ответ

6
  1. Я понимаю, что вы имели в виду «кэш процессора», а не кэш-памяти

  2. Ссылка выше хорошо: предложение «писать много данных через CPU» является не Окна конкретных

  3. Вот еще одна вариация на ту же тему:

  4. Вот статья о Linux и кэш процессора:

Примечание:

В этом (очень, очень низкий) уровень, "Linux" ! = "Unix"

+0

Спасибо за полезность. Это действительно хорошее сообщество с полезными людьми ... не могли бы вы объяснить, как я должен использовать 'echo 3>/proc/sys/vm/drop_caches' в моей программе на C с небольшим примером кода. –

+0

Одна из частей красоты * nix (Unix вообще и Linux специально) заключается в том, что вы можете рассматривать «все как файл». В частности: 'fopen ("/proc/sys/vm/drop_caches "," w "); fprintf (fp, "3"); fclose (fp); '. PS: Если это * * домашнее задание, пожалуйста, используйте тег «домашняя работа» в своих вопросах. – paulsm4

+0

Я использую fopen ("proc/sys/vm.drop_caches", "w") .... но как я могу проверить, действительно ли мой кеш был очищен. @ paulsm4 Спасибо, что были добрыми и помогали раньше. Надеюсь, вы тоже поможете на этот раз. :) –

2

Если вы пишете пользовательский режим (а не в режиме ядра), и если это однопоточность, то вам действительно нечего беспокоиться о том, чтобы сбросить ваш кеш в первую очередь. Ваша программа пользовательского режима может просто забыть, что она существует; это просто для ускорения выполнения вашей программы, и ОС управляет ею через MMU процессора.

Есть только несколько причин, я могу думать о том, что вы, возможно, на самом деле хотите, чтобы очистить кэш из приложения пользовательского режима:

  1. Ваше приложение предназначено для запуска на симметричной многопроцессорной системе, или имеет транзакции данных с внешним оборудованием)
  2. Вы просто проверяете свой кеш на какой-то тест производительности (в этом случае вам, вероятно, стоит написать свой тест для работы в режиме ядра, возможно, в качестве драйвера).

В любом случае предполагается, что вы используете Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

Это предполагает, что вы есть блок памяти, который вы только что написал, и вы хотите, чтобы убедиться, что он вымывается из кэша обратно в основную память. Блок начинается с указанного адреса, и это-байт долго, и это в одном из двух тайников (или оба):

ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

Обычно вы бы только нужно промывать DCACHE, так как при записи данных в «памяти "(т.е. к кешу), это обычно данные, а не инструкции.

Если вы хотите сбросить «весь кеш» по какой-то странной причине тестирования, вы можете malloc() большой блок, который, как вы знаете, больше, чем кеш вашего процессора (стреляйте, делайте его в 8 раз больше!), напишите в него старый мусор и просто промойте весь этот блок.

Смотрите также: How to perform cache operations in C++?

+0

Спасибо за то, что так полезно. Как я могу узнать размер кеша процессора в ubuntu/unix/linux..а я хочу очистить весь кеш –

+0

См. Http://superuser.com/questions/48505/how-to-find-virtual-memory -size-and-cache-size-of-a-linux-system См. также мой 2-й ответ, который, я думаю, скорее всего похож на то, что вы ищете ... Я бы сказал «больше по строкам что вам нужно », за исключением того, что я думаю, что ваша цель сбросить кеш для тестирования производительности ошибочна. То, что, по моему мнению, будет иметь большее значение для тестирования производительности, - это проверить производительность вашего кода ПОСЛЕ того, как он загрузится в кеш, запустив его один раз, чтобы получить его в кеш, а затем использовать таймер для проверки, возможно, 10 000 раз и деление времени на 10000. – phonetagger

+0

'error: asm/cachectl.h: Нет такого файла или каталога' gnu-gcc-компилятор на linux выдает эту ошибку. Любая идея, как его решить ... такая, что он принимает cachectl.h в качестве файла заголовка. –

1

ОК, извините мой первый ответ. Позднее я прочитал ваши последующие комментарии под вашим вопросом, поэтому теперь я понимаю, что вы хотите очистить INSTRUCTION CACHE, чтобы загрузить свою программу (или ее части) из кеша, чтобы при проверке ее производительности вы также тестировали его начальное время загрузки из основной памяти в кэш команд. Вам также нужно очистить любые данные, которые ваш код будет использовать в основной памяти, чтобы данные и код были свежими?

Прежде всего я хотел бы упомянуть, что основная память сама по себе также является формой кеша, а ваш жесткий диск (либо программа на диске, либо место подкачки на диске) является самым низким, самым медленным местом для вашей программы инструкции могут быть получены. Тем не менее, когда вы впервые запускаете процедуру в первый раз, если она еще не загружена в основную память с диска из-за того, что она находится рядом с другим уже выполненным кодом, тогда сначала должны быть загружены его команды CPU с диска. Это занимает порядка или больше дольше, чем загрузка его из основной памяти в кеш. Затем, как только он загружается в основную память, требуется примерно на порядок больше времени для загрузки из основной памяти в кеш, чем требуется для загрузки из кэша в сборщик команд процессора. Поэтому, если вы хотите проверить производительность вашего холодного запуска вашего кода, вам нужно решить, что означает «холодный старт» ... вытащить его из диска или вытащить его из основной памяти. Я не знаю никакой команды «вымыть» инструкции/данные из основной памяти, чтобы поменять местами, поэтому очистка до основной памяти примерно такая же, как вы можете (что я знаю), но имейте в виду что ваши результаты теста могут по-прежнему отличаться от первого запуска (когда он может вытащить его из диска) в последующие прогоны, даже если вы очистите кеш команд.

Теперь, как можно было бы промыть кеш инструкций, чтобы убедиться, что их собственный код выведен в основную память?

Если бы мне было нужно это сделать (очень странно, по моему мнению), я бы, вероятно, начинал с нахождения длины & приблизительного размещения моих функций в памяти. Поскольку я использую Linux, я бы выпустил команду «objdump -d {myprogram}> myprogram.dump.txt», тогда я бы открыл файл myprogram.dump.txt в редакторе и выполнил поиск функций, которые хочу сбросить и выяснить, как долго они вычитают свой конечный адрес из своего начального адреса, используя шестнадцатеричный калькулятор. Я бы записал размеры каждого из них. Позже я добавил вызовы cacheflush() в моем коде, указав ему адрес каждой функции, которую я хочу сбросить как «addr», и длину, которую я нашел как «nbytes», и ICACHE. Просто для безопасности я, вероятно, выдул бы немного &, добавив около 10% к размеру, на всякий случай, я сделаю несколько настроек к коду и забуду отрегулировать nbytes. Я бы сделал вызов cacheflush(), как это для каждой функции, которую я хочу отключить. Затем, если мне нужно также очистить данные, если они используют глобальные/статические данные, я могу их также очистить (DCACHE), но если это данные стека или кучи, реально нет ничего реалистичного, что я могу (или должен) делать для флеша что из кеша. Попытка сделать это будет упражнением в глупости, потому что это создаст условие, которое никогда или очень редко существовало бы при нормальном исполнении. Предполагая, что вы используете Linux ...

#include <asm/cachectl.h> 

int cacheflush(char *addr, int nbytes, int cache); 

...where cache is one of: 
    ICACHE Flush the instruction cache. 
    DCACHE Write back to memory and invalidate the affected valid cache lines. 
    BCACHE Same as (ICACHE|DCACHE). 

BTW, это домашнее задание для класса?

+0

В: Это применимо только в режиме ядра, правильно? – paulsm4

+0

@ paulsm4 - Страница руководства Linux ничего об этом не говорит. Хммм. Чтение на странице man ... (я предполагаю, что вы используете Linux, верно? Если да, то вы попробовали команду «man cacheflush»?) ... внизу, я вижу две вещи в моей версии страницы руководства, которые вызывают беспокойство ... »BUGS - текущая реализация игнорирует аргументы addr и nbytes, поэтому весь кеш всегда очищается». И далее вниз ... »ПРИМЕЧАНИЕ. Этот системный вызов доступен только в системах на базе MIPS. Он не должен использоваться в программах, предназначенных для переносимости». – phonetagger

+1

@ paulsm4 error: asm/cachectl.h: Нет такого файла или каталога, который gnu-gcc-компилятор на linux вызывает эту ошибку. Любая идея, как его решить ... такая, что он принимает cachectl.h в качестве файла заголовка. –

1

Это как Intel предлагает очистка кэша:

mem_flush(const void *p, unsigned int allocation_size){ 
    const size_t cache_line = 64; 
    const char *cp = (const char *)p; 
    size_t i = 0; 

    if (p == NULL || allocation_size <= 0) 
      return; 

    for (i = 0; i < allocation_size; i += cache_line) { 
      asm volatile("clflush (%0)\n\t" 
         : 
         : "r"(&cp[i]) 
         : "memory"); 
    } 

    asm volatile("sfence\n\t" 
       : 
       : 
       : "memory"); 
} 
+0

какой у вас источник? – horro