Рассмотрим один доступ к памяти (одно чтение или однократное чтение, а не чтение + запись) SSE-инструкции на процессоре x86. Команда получает доступ к 16 байтам (128 бит) памяти, а доступная ячейка памяти соответствует 16 байтам.
В документе "Белая книга с памятью архитектуры архитектуры Intel® 64" указано, что для "Инструкции, которые читают или записывают квадрат (8 байт), адрес которого выровнен по границе 8 байтов", операция памяти, как представляется, выполняется как единая память доступ независимо от типа памяти.
Вопрос: Существуют ли процессоры Intel/AMD/etc x86, которые гарантируют, что чтение или запись 16 байтов (128 бит), выровненных по границе 16 байтов, выполняются как один доступ к памяти?, какой конкретный тип процессора он (Core2/Atom/K8/Phenom/...)? Если вы даете ответ (да/нет) на этот вопрос, , пожалуйста, также укажите метод, который использовался для определения ответа - поиск в PDF-документе, проверка грубой силы, математическое подтверждение или любой другой метод, который вы используется для определения ответа.
Этот вопрос относится к таким проблемам, как http://research.swtch.com/2010/02/off-to-races.html
Update:
Я создал простую тестовую программу на C, которую вы можете запускать на своих компьютерах. Пожалуйста, скомпилируйте и запустите его на своих процессорах Phenom, Athlon, Bobcat, Core2, Atom, Sandy Bridge или любых SSE2-совместимых процессорах, которые у вас есть. Спасибо.
// Compile with:
// gcc -o a a.c -pthread -msse2 -std=c99 -Wall -O2
//
// Make sure you have at least two physical CPU cores or hyper-threading.
#include <pthread.h>
#include <emmintrin.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
typedef int v4si __attribute__ ((vector_size (16)));
volatile v4si x;
unsigned n1[16] __attribute__((aligned(64)));
unsigned n2[16] __attribute__((aligned(64)));
void* thread1(void *arg) {
for (int i=0; i<100*1000*1000; i++) {
int mask = _mm_movemask_ps((__m128)x);
n1[mask]++;
x = (v4si){0,0,0,0};
}
return NULL;
}
void* thread2(void *arg) {
for (int i=0; i<100*1000*1000; i++) {
int mask = _mm_movemask_ps((__m128)x);
n2[mask]++;
x = (v4si){-1,-1,-1,-1};
}
return NULL;
}
int main() {
// Check memory alignment
if ( (((uintptr_t)&x) & 0x0f) != 0 )
abort();
memset(n1, 0, sizeof(n1));
memset(n2, 0, sizeof(n2));
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
for (unsigned i=0; i<16; i++) {
for (int j=3; j>=0; j--)
printf("%d", (i>>j)&1);
printf(" %10u %10u", n1[i], n2[i]);
if(i>0 && i<0x0f) {
if(n1[i] || n2[i])
printf(" Not a single memory access!");
}
printf("\n");
}
return 0;
}
В моем ноутбуке есть процессор Core Duo (не Core2). Этот конкретный процессор выходит из строя при тестировании, он реализует чтение/запись 16-байтовых данных с зернистостью 8 байтов. Выход:
0000 96905702 10512
0001 0 0
0010 0 0
0011 22 12924 Not a single memory access!
0100 0 0
0101 0 0
0110 0 0
0111 0 0
1000 0 0
1001 0 0
1010 0 0
1011 0 0
1100 3092557 1175 Not a single memory access!
1101 0 0
1110 0 0
1111 1719 99975389