문제

C99를 얻었다면 restrict 키워드 권리, 포인터 자격을 갖춘 자격을 갖춘 데이터는 aliasing을 통해 컴파일러의 백 뒤에 수정되지 않는다는 약속입니다.

대조적으로, 내가 이해하는 방식 const 예선은 주어진 객체가 코드를 쓰는 코드 뒤에서 수정되지 않는다는 컴파일러 강화 문서입니다. 컴파일러는 부작용으로 힌트를 얻을 수 있지만 프로그래머로서 나는 정말로 신경 쓰지 않습니다.

비슷한 방식으로 restrict 사용자가 통화 기간 동안 독점 액세스 ( "별명을 피하십시오"또는 더 강한 것)를 보장 해야하는 요구 사항으로 기능 프로토 타입의 예선? "문서"로 사용해야합니까?

또한, 사실에 이해할 것이 있습니까? restrict ( const 하다) ?

편집 : 나는 원래 그것을 믿었다 restrict 스레드 코드에 영향을 미칠 수 있지만, 이것은 잘못된 것처럼 보이므로 혼란스러운 독자를 피하기 위해 질문의 스레드에 대한 참조를 제거합니다.

도움이 되었습니까?

해결책

제한 키워드에 대한 최선의 '직관'은 (컴파일러에 대한 프로그래머가) 포인터의 수명에 따라 해당 포인터를 통해 액세스 된 메모리가 다른 포인터를 통해서만 해당 포인터를 통해서만 액세스 할 것이라는 보증이라는 것입니다. 또는 참조 또는 글로벌 주소. 따라서 포인터가 포인터와 메모리의 속성으로 포인터에있어서 포인터가 범위를 벗어날 때까지 둘을 함께 묶는 것이 중요합니다.

다른 팁

Chris Dodd는 키워드에 대한 올바른 설명을 가지고 있습니다. 특정 플랫폼에서는 성능의 이유로 매우 중요 할 수 있습니다. 컴파일러가 해당 포인터를 통해 데이터를 레지스터에로드 한 후에는 다시 할 필요가 없다는 것을 알리기 때문입니다. 이 보증이 없으면 컴파일러는 매번 포인터를 통해 데이터를 다시로드해야합니다. 로드 하이터 스토어.

const 그리고 restrict 다른 개념이며, 그렇지 않습니다. const 암시합니다 restrict. 모두 const 말한다 그 기능의 범위 내에서. ㅏ const 포인터는 여전히 별명 일 수 있습니다. 예를 들어 고려하십시오 :

int foo( const int *a, int * b )
{
   *b *= 2;
   return *a + *b; // induces LHS: *a must be read back immediately
                   // after write has cleared the store queue
}

직접 글을 쓸 수는 없습니다 a 이 기능에서는 Foo라고 부르는 것이 다음에는 완벽하게 합법적입니다.

int x = 3;
foo( &x, &x );  // returns 12

restrict 다른 보증입니다 : 약속 a != b 모든 전화에서 foo().

나는 에 대해 쓰여진 restrict 키워드 및 성능의 길이, 그리고 Mike Acton도 마찬가지입니다. 우리는 특정 인 주문 PowerPC에 대해 이야기하지만 X86에는로드 타격 스토어 문제가 존재하지만 X86의 주문 외의 실행은 스톨이 프로파일에서 분리하기가 더 어려워집니다.

그리고 그냥 강조하기 위해 : 이것은입니다 ~ 아니다 성능에 전혀 관심이 있다면 비전 또는 조기 최적화. restrict 올바르게 사용하면 상당한 속도를 높일 수 있습니다.

당신이 아는 대부분의 것이 잘못되었습니다!

Const ~ 아니다 컴파일러의 뒤에서 무언가가 바뀌지 않도록 보장하십시오. 그 일은 중지뿐입니다 글쓰기에서 그 자리까지. 다른 것이 여전히 그 위치에 쓸 수있을 수 있으므로 컴파일러는 일정하다고 가정 할 수 없습니다.

다른 사람들이 말했듯이, 제한 예선은 별명에 관한 것입니다. 실제로 C 표준화의 첫 번째 라운드 동안 "Noalias"키워드에 대한 제안이있었습니다. 불행히도, 제안은 상당히 제대로 쓰여졌다. Dennis Ritchie가 그 과정에서 참여했을 때의 유일한 시간을 자극했다. 그는 "Noalias가 가야한다는 효과에 대해 무언가를 말한 편지를 썼을 때, 이것은 협상에 열려 있지 않다. "

말할 것도없이, '노리아'는 C의 일부가되지 않았다. 그것을 위해, 그 이름은 너무 오염되어 그것을 사용하려고 노력하는 사람도 의심했습니다.

어쨌든, 제한의 주요 의도는이 항목의 별칭이 없을 것이라고 컴파일러에게 알리는 것입니다. 이에 대한 한 가지 이유는 일시적으로 레지스터에 물건을 저장할 수 있기 때문입니다. 예를 들어 다음과 같은 것을 고려하십시오.

void f(int *a, int *b, int *c) { 
    for (int i=0; i<*a; i++)
        *b += c[i];
}

컴파일러는 실제로 I를 레지스터에 넣고 *a를 레지스터에로드하려고하므로 루프의 다른 반복을 실행할지 여부를 결정할 때마다 서로 등록하는 값의 값을 비교합니다. 불행히도,이 기능을 사용한 사람이 완전히 미쳤고 A == B로 불렀다면, 루프 내부에 *b에 쓸 때마다 새로운 값도 *a의 값입니다. - 루프의 반복마다 메모리에서 *A를 읽어야합니다. 만일을 대비하여 그것을 부르는 사람은 완전히 미쳤다. 제한을 사용하면 컴파일러에 A와 B가 항상 뚜렷하다고 가정 할 때 코드를 생성 할 수 있으므로 *A에 쓰는 것은 *B (또는 그 반대)를 절대 변경하지 않습니다.

당신의 이해는 크게 정확합니다. 그만큼 restrict 한정자는 단순히 소위 포인터가 액세스 한 데이터가 그 정확한 포인터로 액세스합니다. 그것은 쓴대로 읽기 웰에 적용됩니다.

컴파일러는 동시 스레드를 신경 쓰지 않으며 코드를 다르게 생성하지 않으며 원하는대로 자신의 데이터를 깎을 수 있습니다. 그러나 어떤 포인터 작업이 글로벌 메모리를 바꿀 수 있는지 알아야합니다.

Restrict 또한 인간에게 주어진 기능이 비 알리 아스 매개 변수의 가정으로 구현된다는 API 경고를 전달합니다.

컴파일러에 관한 한 사용자의 잠금은 필요하지 않습니다. 그것은 단지 그것을 올바르게 읽었는지 확인하고 싶어합니다. 추정된 코드별로 클로버링해야합니다 컴파일러가 생성되어야했습니다, 아무도없는 경우 restrict 예선. 첨가 restrict 그 우려에서 해방됩니다.

마지막으로, 컴파일러는 더 높은 최적화 수준에서 데이터 유형을 기반으로 가능한 앨리어싱을 이미 분석 할 가능성이 높습니다. restrict 동일한 유형의 데이터에 대한 여러 포인터가있는 기능에 주로 중요합니다. 이 주제로부터 교훈을 얻고 당신이하는 의도적 인 별칭이 union.

우리는 볼 수있다 restrict 행동 :

void move(int *a, int *b) {     void move(int *__restrict a, int *__restrict b) {
    a[0] = b[0];                    a[0] = b[0];
    a[1] = b[0];                    a[1] = b[0];
}                               }
    movl    (%edx), %eax            movl    (%edx), %edx
    movl    %eax, (%ecx)            movl    %edx, (%eax)
    movl    (%edx), %eax            movl    %edx, 4(%eax)
    movl    %eax, 4(%ecx)

오른쪽 열에서 restrict, 컴파일러는 다시 읽을 필요가 없었습니다 b[0] 기억으로부터 . 읽을 수있었습니다 b[0] 그리고 등록에 보관하십시오 %edx, 그리고 레지스터를 메모리에 두 번 저장하십시오. 왼쪽 열에서 매장이 a 변경되었을 수 있습니다 b.

표준에 더 친숙한 사람은 아마도 더 나은 대답을 할 수 있지만, 나는 그것을 한 번 줄 것입니다.

"컴파일러 뒷면 뒤에서 데이터가 수정되지 않음"은 "휘발성"의 반대와 비슷합니다.

"Const"는 프로그래머 앞에서 데이터가 수정되지 않음을 의미합니다. 즉, 그녀는 "const"로 표시된 서명자를 통해 데이터를 수정할 수 없습니다 ( int const *pi, 이름 pi Const는 아니지만 *pi 이다). 데이터는 다른 서명자를 통해 수정 가능할 수 있습니다 (결국 비 초보 데이터는 Const 데이터로서 함수로 전달 될 수 있음).

"제한"이 포인터를 자격으로하는 것이 핵심입니다. 포인터는 C의 별칭 데이터를위한 유일한 방법이므로 두 개의 다른 이름을 통해 일부 데이터에 액세스 할 수있는 유일한 방법입니다. "제한"은 하나의 액세스 경로로 데이터 액세스를 제한하는 것입니다.

이것은 An의 예일 수 있습니다 극도로 좁은 도메인이지만 Altera의 NIOS II 플랫폼은 FPGA 내에서 사용자 정의 할 수있는 소프트 코어 마이크로 컨트롤러입니다. 그런 다음 해당 마이크로의 C 소스 코드 내에서 C-to-Hardware 도구를 사용하여 소프트웨어가 아닌 사용자 정의 하드웨어를 사용하여 내부 루프 속도를 높일 수 있습니다.

거기에서 __restrict__ 키워드 (C99와 동일합니다 restrict) C2H 도구가 포인터 작동의 하드웨어 가속도를 올바르게 최적화 할 수 있도록합니다. 병행하여 순차적으로 대신. 적어도이 경우에 restrict 간단합니다 ~ 아니다 인간 소비를위한 것입니다. 또한보십시오 태양 페이지 on restrict, 첫 번째 줄이 말하는 곳

사용 restrict C 프로그램의 적절한 예선은 컴파일러가 상당히 빠른 실행 파이브를 생성 할 수 있습니다.

C2H에서 더 많은 것을 읽는 데 관심이 있다면 이 PDF C2H 결과 최적화에 대해 논의합니다. 섹션 __restrict__ 20 페이지에 있습니다.

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