Я пытаюсь воспроизвести пример 6 из Галереи эффектов кэша процессора .
В статье приведена эта функция (в C #) в качестве примера проверки ложного обмена:
private static int[] s_counter = new int[1024];
private void UpdateCounter(int position)
{
for (int j = 0; j < 100000000; j++)
{
s_counter[position] = s_counter[position] + 3;
}
}
Если мы создадим потоки, передающие этой функции аргументы 0, 1, 2, 3, вычисление займет много времени (автор получил 4,3 секунды). Если мы передадим, например, 16, 32, 48, 64, мы получим намного более хорошие результаты (0,28 секунды).
Я предложил следующую функцию в Rust:
pub fn cache_line_sharing(arr: [i32; 128], pos: usize) -> (i32, i32) {
let arr = Arc::new(arr);
let handles: Vec<_> = (0..4).map(|thread_number| {
let arr = arr.clone();
let pos = thread_number * pos;
thread::spawn(move || unsafe {
let p = (arr.as_ptr() as *mut i32).offset(pos as isize);
for _ in 0..1_000_000 {
*p = (*p).wrapping_add(3);
}
})
}).collect();
for handle in handles {
handle.join().unwrap();
}
(arr[0], arr[1])
}
Сравнительный анализ с двумя наборами аргументов (0, 1, 2, 3 и 0, 16, 32, 48) дает мне почти идентичные результаты: 108,34 и 105,07 микросекунд.
Я использую критерий для оценки. У меня MacBook Pro 2015 с процессором Intel i5-5257U (2,70 ГГц). Моя система сообщает, что 64B
размер строки кэша.
Если кто-то захочет увидеть мой полный код тестирования, вот ссылки:
- lib.rs
- cache_lines.rs
Я хочу понять проблему и найти способ воспроизвести результаты, аналогичные приведенным в статье.