2009-06-28 5 views
11

Pentium과 같은 Intel의 32 비트 프로세서는 64 비트 데이터 버스를 가지므로 액세스 당 8 바이트를 가져옵니다. 이를 기반으로,이 프로세서가 주소 버스에서 방출하는 실제 주소는 항상 8의 배수라고 가정합니다.32 비트 Intel 프로세서의 메모리 정렬

첫째,이 결론이 맞습니까?

둘째, 올바른 경우 데이터 구조체 멤버를 8 바이트 경계에 정렬해야합니다. 하지만 사람들은이 프로세서 대신 4 바이트 정렬을 사용하는 것을 보았습니다.

그렇게하는 것이 어떻게 정당화 될 수 있습니까?

+1

이 질문의 의미는 모르겠지만 프로그래밍과 관련하여 어떻게 관련되어 있는지, 그리고 이것이 나를 어떻게 영향을 줄 수 있는지에 대해 흥미가 있습니다. 이 저수준 유형 물건에 대한 기본 소개를 어디에서 읽을 수 있습니까? –

+4

"모든 프로그래머가 메모리에 대해 알아야 할 내용"참조 : http://people.redhat.com/drepper/cpumemory.pdf – Crashworks

+1

"요청 된 읽기는 항상 8의 배수입니다."에서 "데이터가 항상 시작되어야합니다 8 바이트 경계 "? 나는 이들 사이의 논리적 연결을 보지 못했다. 데이터가 8 바이트 경계를 넘지 않는 한, 우리는 훌륭합니다. 그렇죠? – jalf

답변

14

일반적인 경험 법칙 (Intels 및 AMD의 최적화 매뉴얼에서 직접 확인)은 모든 데이터 유형이 자체 크기로 정렬되어야한다는 것입니다. int32은 32 비트 경계에 맞추고, int64은 64 비트 경계에 정렬해야합니다. char는 어디서나 잘 어울립니다.

또 다른 어림짐작은 "컴파일러가 정렬 요구 사항에 대해 말한 것"입니다. 컴파일러가 올바른 패딩과 오프셋을 추가하여 데이터에 효율적으로 액세스 할 수 있기 때문에 걱정할 필요가 없습니다.

유일한 예외는 대부분의 컴파일러에서 수동으로 정렬을해야하는 SIMD 명령어를 사용하는 경우입니다. 정확하면

둘째, 만약 하나는 8 바이트 경계 상에 데이터 구조 부재를 정렬한다. 그러나 나는 사람들이이 프로세서 대신에 4 바이트 정렬 을 사용하는 것을 보았습니다.

어떻게 차이가 나는지 알 수 없습니다. CPU는 이러한 4 바이트를 포함하는 64 비트 블록에 대한 읽기를 단순히 발행 할 수 있습니다. 즉, 요청 된 데이터 이전에 4 바이트가 추가되거나 그 이후에 추가 바이트가 4 바이트가됩니다. 그러나 두 경우 모두 단일 읽기만 필요합니다. 32 비트 폭 데이터의 32 비트 정렬은 64 비트 경계를 넘지 않도록합니다.

+0

4 바이트가 하나의 64 비트 청크에 걸친 경우가 아닙니다. –

+0

4 바이트 경계에 정렬되면 어떻게됩니까? – jalf

+5

나는이 간단한 추론을 놓쳤다는 것을 믿을 수 없다. 4 바이트로 동일한 성능을 달성 할 때 왜 8 바이트 정렬에서 4 개의 여분의 바이트를 낭비합니까? Jalf에게 감사드립니다. 당신은 완벽하게 이해합니다. –

6

물리적 버스는 64 비트 폭 ... (8)의 복수 -> 예

그러나,이 두 가지 이상의 요인은 고려 :

  1. 일부 x86 명령어 세트는 바이트가 해결됩니다. 일부는 32 비트 정렬 (그 이유는 당신이 4 바이트 것을 가지고)입니다. 그러나 no (core) 명령은 64 비트 정렬됩니다. CPU가 잘못 정렬 된 데이터 액세스를 처리 할 수 ​​있습니다.
  2. 성능에 신경 쓰면 주 메모리가 아닌 캐시 라인에 대해 생각해야합니다. 캐시 라인이 훨씬 넓습니다.
+0

나는 이해하지 못한다. 펜티엄과 같은 프로세서는 주소 버스에 배수가 8 개인 것에 동의합니다. 그렇다면 4 바이트 정렬이 괜찮다고합니다. 주소 0x000044444를 생각해보십시오. 4 바이트 정렬이지만 프로세서는 8의 배수가 아니기 때문에 주소 라인에서이 주소를 방출하지 않습니다. 따라서이 주소에서 메모리를 가져 오려면 두 개의 페치가 필요합니다. 4 바이트 정렬은 어떻게 정당화됩니까? –

+2

두 번 가져 오기가 필요한 이유는 무엇입니까? 단순히 모든 데이터를 0x000044440에서 0x000044447까지 요청할 것이고 0x000044444-0x000044447에 관심이 있으니 무엇이 문제입니까? – jalf

+0

왜 지침 정렬에 대해 이야기하고 있는지, 그건 의미가 없습니다. NOP와의 경계에 대한 지침을 채우는 것은 아무 것도 달성하지 못합니다. –

0

데이터가 임의로 (예 : 경계를 넘어서는) 정렬되지 않는 한, 나는별로 중요하지 않다고 생각합니다. 데이터의 올바른 주소와 오프셋은 하드웨어의 간단한 AND 구성으로 찾을 수 있습니다. 하나의 읽기 액세스로 하나의 값을 얻지 못하면 속도가 느려집니다. 컴파일러가 보통 작은 값 (바이트 등)을 함께 놓는 이유는 특정 오프셋에있을 필요가 없기 때문입니다. 단락은 짝수 주소에, 32 비트는 4 바이트 주소에, 64 비트는 8 바이트 주소에 있어야합니다.

내부 데이터 액세스 및 선형 데이터 액세스를 캐싱하면 상황이 달라집니다.

2

8 바이트 정렬로 변경하면 ABI 변경이 이루어 지므로 한계가 있습니다.

다른 누군가가 이미 말했듯이, 캐시 라인이 중요합니다. 실제 메모리 버스의 모든 액세스는 캐시 라인 (x86, IIRC의 경우 64 바이트)을 기준으로합니다. 이미 언급 된 "모든 프로그래머가 메모리에 대해 알아야 할 사항"문서를 참조하십시오. 따라서 실제 메모리 트래픽은 64 바이트로 정렬됩니다.

1

참조 할 64 비트 버스가 캐시를 피드합니다. CPU로서 항상 전체 캐시 라인을 읽고 씁니다. 캐시 라인의 크기는 항상 8의 배수이며 실제 주소는 실제로 8 바이트 오프셋으로 정렬됩니다.

캐시 간 전송은 외부 데이터 버스를 사용하지 않으므로 해당 버스의 너비는 무의미합니다.