문제

정렬 된 메모리 액세스와 정렬되지 않은 메모리 액세스의 차이점은 무엇입니까?

TMS320C64X DSP에서 작업하고 있으며 고유 함수 (어셈블리 지침의 C 함수)를 사용하고 싶습니다.

ushort & _amem2(void *ptr);
ushort & _mem2(void *ptr);

어디 _amem2 2 바이트의 정렬 된 액세스를 수행합니다 _mem2 정렬되지 않은 액세스를 수행합니다.

언제 어느 것을 사용해야합니까?

도움이 되었습니까?

해결책

정렬 된 메모리 액세스는 포인터 (정수로서)가 정렬이라고하는 유형 별 값의 배수임을 의미합니다. 정렬은 유형이 CPU에 유형이 있어야하거나 저장 해야하는 자연 주소 다중입니다. 예를 들어, CPU는 2 바이트 부하 또는 매장이 2 개의 배수 주소를 통해 수행되도록 요구할 수 있습니다. 작은 원시 유형 (4 바이트 미만)의 경우 정렬은 거의 항상 유형의 크기입니다. Structs의 경우, 정렬은 일반적으로 모든 구성원의 최대 정렬입니다.

C 컴파일러는 항상 "올바른"정렬을 만족하는 주소로 선언하는 변수를 넣습니다. 따라서 PTR이 UINT16_T 변수를 가리키면 정렬되고 _AMEM2를 사용할 수 있습니다. 예를 들어 I/O를 통해 수신 된 포장 된 바이트 배열 또는 문자열 중간에 바이트에 액세스하는 경우에만 _MEM2를 사용해야합니다.

다른 팁

많은 컴퓨터 아키텍처는 각각 여러 바이트의 "단어"로 메모리를 저장합니다. 예를 들어, 인텔 32 비트 아키텍처는 32 비트의 단어, 각각 4 바이트를 저장합니다. 그러나 메모리는 단일 바이트 레벨로 해결됩니다. 따라서 주소는 "정렬"될 수 있으며, 이는 단어 경계에서 시작하거나 "정렬되지 않은"것으로 시작하여 그렇지 않음을 의미합니다.

특정 아키텍처에서는 특정 메모리 작업이 정렬되지 않은 주소에서 느리거나 완전히 허용되지 않을 수 있습니다.

따라서 주소가 올바른 주소에 정렬되어 있다는 것을 알고 있으면 속도로 _AMEM2 ()를 사용할 수 있습니다. 그렇지 않으면 _mem2 ()를 사용해야합니다.

정렬 된 주소는 해당 액세스 크기의 배수 인 주소입니다.

  • 4 개 중 4 개 주소에 4 바이트 단어 액세스가 정렬됩니다.
  • 주소 (예 :) 3에서 4 바이트 액세스는 조정되지 않은 액세스가됩니다.

그럴 가능성이 큽니다 _MEM2 정렬되지 않은 액세스에도 작동하는 기능은 코드에서 올바른 정렬을 작동시키는 데 덜 최적입니다. 이것은 _MEM2 기능은 그보다 비용이 많이들 수 있습니다 _AMEM2 버전.

따라서 성능이 필요할 때 (특히 액세스 대기 시간이 높다는 것을 알면) 정렬 된 액세스를 사용할 수있는시기를 식별하는 것이 현명합니다. 그만큼 _AMEM2 이 목적을 위해 존재합니다. 액세스가 정렬되어 있음을 알 때 성능을 제공합니다.

2 바이트 액세스와 관련하여 정렬 된 작업을 식별하는 것은 매우 간단합니다.
작업의 모든 액세스 주소가 '고도'인 경우 (즉, LSB가 0 인 경우) 2 바이트 정렬이 있습니다. 이것은 쉽게 확인할 수 있습니다.

if (address & 1) // is true
    /* we have an odd address; not aligned */
else
    /* we have an even address; its aligned to 2-bytes */

나는 이것이 선택된 답변이있는 오래된 질문이라는 것을 알고 있지만 아무도 정렬되지 않은 메모리 액세스와 정렬되지 않은 메모리 액세스의 차이점에 대한 답을 설명하는 것을 보지 못했습니다.

DRAM 또는 SRAM 또는 FLASH 또는 기타입니다. SRAM을 간단한 예제로 가져 가십시오. 비트로 구축 된 예제 특정 SRAM은 고정 된 수의 비트와 고정 된 수의 깊이로 구축됩니다. 32 비트의 너비와 몇 줄의 깊이를 가정 해 봅시다.

이 SRAM에서 0x0000을 주소하기 위해 32 비트 쓰기를 수행하면이 SRAM 주변의 메모리 컨트롤러는 단순히 단일 쓰기주기를 행 0으로 수행 할 수 있습니다.

이 SRAM에서 0x0001을 주소하기 위해 32 비트를 작성하면 허용된다고 가정하면 컨트롤러는 행 0을 읽고 바이트 3 개를 수정하고 하나를 보존 한 다음 행 0에 써야합니다. 1 하나의 바이트를 찾은대로 다른 3 바이트를 수정하고 그것을 뒤로 씁니다. 어떤 바이트가 수정되거나 시스템의 엔지니어와 관련이 없습니다.

전자는 정렬되고 후자는 정렬되지 않았으며, 성능 차이는 분명히 4 개의 메모리주기를 수행하고 바이트 레인을 병합하려면 추가 논리가 필요합니다.

주소 0x0000에서 32 비트를 읽으려면 행 0을 한 번 읽으십시오. 그러나 0x0001에서 읽으면서 2 개의 읽기 Row0과 Row1을 수행해야하며 시스템 설계에 따라 64 비트를 프로세서로 다시 보낼 수 있습니다. 또는 메모리 컨트롤러에는 추가 로직이있어 32 비트가 한 번의 버스주기에서 데이터 버스에 정렬되도록합니다.

16 비트 읽기가 조금 더 좋으며, 0x0000, 0x0001 및 0x0002의 읽기는 Row0에서만 읽을 수 있으며 시스템/프로세서 설계를 기반으로 32 비트를 다시 보내면 프로세서가 추출하거나 메모리 컨트롤러에서 이동할 수 있습니다. 프로세서가 회전 할 필요가 없도록 특정 바이트 레인에 착륙합니다. 둘 다가 아니라면 하나 또는 다른 하나는 있어야합니다. 0x0003에서 읽은 것은 위의 바이트 중 하나가 각각에 있기 때문에 Row 0과 Row1을 읽어야합니다. 그런 다음 프로세서가 추출하기 위해 64 비트를 다시 보내거나 메모리 컨트롤러가 비트를 하나의 32 비트 버스 응답으로 결합합니다 ( 프로세서와 메모리 컨트롤러 사이의 버스 가이 예제에서 32 비트의 폭을 가정합니다).

16 비트 쓰기는이 예제에서 항상 하나 이상의 읽기 모형 작성으로 끝납니다. 주소 0x0003 두 행을 읽으십시오.

8 비트 바이트가 포함 된 한 행만 읽으면 한 행의 읽기 고정 제기입니다.

ARMV4는 트랩을 비활성화 할 수 있지만 결과는 위의 예상과 같지 않지만 중요하지 않은 것과 같지 않지만, 현재 암은 정렬되지 않은 허용을 허용하고 제어 레지스터에서 약간 변경할 수있는 위의 동작을 제공 한 다음 정렬되지 않은 중단됩니다. 전송. MIPS는 지금 무엇을하는지 확실하지 않고 허용하지 않았습니다. x86, 68k 등이 허용되었고 메모리 컨트롤러가 가장 많은 작업을 수행해야 할 수도 있습니다.

그것을 명확하게 허용하지 않는 디자인은 성능을위한 것이며 일부 사람들이 프로그래머에게 부담이 될 수있는 것은 프로그래머에 대한 추가 작업이 아니거나 프로그래머에 대한 더 쉬운 일이라고 말할 수 있다고 말하는 것입니다. 정렬되었는지 여부는 8 비트 변수를 만들어 메모리를 저장하지 않는 것이 더 나을 수있는 이유를 알 수 있지만 계속해서 32 비트 단어 또는 레지스터 또는 버스의 자연스런 크기가 무엇이든 연소하십시오. 일부 바이트의 작은 비용으로 성능을 발휘할 수 있습니다. 추가 코드는 말할 것도없이 컴파일러가 추가 해야하는 추가 코드는 32 비트 레지스터를 8 비트 변수, 마스킹 및 간판 확장으로 만들기 위해 추가해야합니다. 레지스터 기본 크기를 사용하는 경우 해당 추가 지침이 필요하지 않습니다. 또한 여러 가지 버스/메모리 와이드 위치에 여러 가지를 포장하고 하나의 메모리주기를 수행하여 수집하거나 작성한 다음 추가 지침을 사용하여 RAM 비용이 드는 레지스터와 지침 수에 대한 세척 사이를 조작 할 수 있습니다.

컴파일러가 항상 대상에 대한 데이터를 올바르게 정렬한다는 데 동의하지 않습니다. 그리고 대상이 정렬되지 않은 지원을하지 않으면 결함에 부딪칩니다. 프로그래머는 컴파일러가 항상 제시 할 수있는 법적 코드에 따라 항상 올바르게 수행 한 경우 이에 대해 이야기 할 필요가 없습니다. 성능이 없다면이 질문에 대한 이유는 없습니다. 정렬 될 유효한 PTR 주소를 제어하지 않거나 정렬되지 않으면 항상 정렬되지 않은 액세스를 사용해야합니다. 지적했다. C 컴파일러는 공허로 선언함으로써 이제 정렬을 올바르게 처리 할 방법이 없으며 보장되지 않습니다. char *prt를 가져 와서 이러한 함수에 공급하는 경우, MEM2 () 함수에 묻힌 추가 코드를 추가하지 않고이 두 기능 외부에 추가 코드를 추가하지 않고 모든 베팅이 컴파일러에 꺼져 있습니다. 따라서 귀하의 질문에 작성된대로 MEM2 ()는 유일한 정답입니다.

DRAM은 데스크탑/노트북에 사용 된 DRAM은 64 또는 72 (ECC) 비트가 크고 모든 액세스 권한이 정렬된다고 말합니다. 메모리 스틱은 실제로 8 비트 너비 또는 16 비트 너비의 칩으로 구성되어 있습니다. (이것은 여러 가지 이유로 전화/태블릿으로 변경 될 수 있습니다) 메모리 컨트롤러와 이상적으로는 적어도 하나의 캐시 가이 DRAM 앞에 놓여있어 버스 너비 읽기 모듈 식 소식보다 작은 정렬되지 않았거나 심지어 정렬 된 액세스가 처리됩니다. 캐시 SRAM이 더 빠르며 DRAM 액세스는 모두 전체 버스 너비 액세스가 정렬됩니다. DRAM 앞에 캐시가없고 컨트롤러가 최대 너비 액세스를 위해 설계된 경우, 바이트 레인을 개별적으로 조명하도록 설계된 경우 (8 비트 넓은 칩을 가정) 읽기 모형이 없습니다. -쓰기하지만 더 복잡한 컨트롤러. 일반적인 유스 케이스가 캐시와 함께있는 경우 (설계에 하나가있는 경우) 각 바이트 레인에 대한 컨트롤러에 추가 작업을하는 것은 의미가 없지만 전체 버스 너비 크기의 전송을 수행하는 방법을 알고 있어야합니다. 또는 배수.

_MEM2가 더 일반적입니다. PTR이 정렬되었는지 여부에 관계없이 작동합니다. _AMEM2는 더 엄격합니다. PTR을 정렬해야합니다 (아마도 약간 더 효율적이지만). 따라서 PTR이 항상 정렬되도록 보장 할 수없는 한 _MEM2를 사용하십시오.

많은 프로세서는 메모리 액세스에 정렬 제한을 가지고 있습니다. 정렬되지 않은 액세스는 예외 인터럽트 (예 : ARM)를 생성하거나 단지 느린 (예 : x86)입니다.

_mem2 아마도 2 개의 바이트를 가져오고 Shift 및 Bitwise 작업을 사용하여 16 비트를 사용하여 구현 될 수 있습니다.

_amem2 아마도 지정된 PTR에서 16 비트 Ushort를 읽을 것입니다.

TMS320C64X를 구체적으로 알지 못하지만 16 비트 메모리 액세스에 16 비트 정렬이 필요하다고 생각합니다. 그래서 당신은 사용할 수 있습니다 _mem2 항상 그러나 성과 페널티와 함께 _amem2 PTR이 짝수 주소임을 보장 할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top