문제

나는 많은 행렬 산술을하고 있으며 C99를 활용하고 싶습니다. restrict 포인터 예선.

매트릭스를 포인터로 포인터로 설정하여 쉽게 구독 할 수 있도록합니다.

int **A = malloc (ncols * sizeof(int *));
A[0] = malloc (nrows * ncols * sizof(int));
for (int i=1; i < ncols; i++) {
    A[i] = A[0] + i*nrows;
}

이제 매트릭스 곱셈 기능의 경우

void mmultiply ( int nrows, int ncols, int **Out, int **A, int **B);

인수의 두 가지가 제한된 것으로 자격이 있어야합니까? 유효한 구문이지만 int *restrict *restrict 와 다르게 행동합니다 int **restrict.

그런 다음 포인터가 제대로 제한되면 A[0][col*nrows + row] 한정되지 않은? (즉, 컴파일러가 i 매트릭스에 액세스하십시오 A[col][row] 값의 경우 row 그렇게 row < nrow)? 아니면 단순히 일관성을 유지해야합니까?

도움이 되었습니까?

해결책

첫 번째 질문 인 "예"의 경우 둘 다 사용하면 다른 것을 의미합니다. restrict 특히 포인터도 별명을받지 못한다. 그것이 어떤 차이를 만들 것인지에 관해서는 : 이론적으로 예, 실제로, 그것은 최적화에 따라 다릅니다.

두 번째 질문 인 "예"의 경우 행 포인터를 통해 액세스 할 수있는 모든 것이 행 포인터를 통해서만 액세스한다고 가정합니다.

당신은 던질 수 있습니다 const 거기에도.

마지막으로, 이것이 -o2, -o3 또는 -os에서 GCC 인 경우 컴파일러는 이미 유형을 기반으로 별명 분석을 수행하고 있습니다. 다른 컴파일러 도이 작업을 수행한다고 확신합니다. 이는 포인터와 INT를 제한하는 것이 이미 이해되며, 서로에게 저장할 수있는 배열 만 남습니다.

요약하면, Optimizer는 포인터가 ints로 저장되지 않는다고 가정 할 것이며, 루프 중에 포인터 쓰기를하지 않는다는 것을 알고 있습니다.

따라서 제한 사항만으로 동일한 코드를 얻을 수 있습니다.

다른 팁

외부 (두 번째) 제한은 컴파일러에 포인터 (a, b 및 out) 별명이 없음을 알려줍니다. 내부 (첫 번째) 제한은 컴파일러에 int의 배열 중 어느 것도 (포인터 배열의 요소에 의해 지적 된) 별칭을 알려줍니다.

0] [col*nrows + row]와 [col] [row]를 모두 액세스하면 내부 제한을 위반하므로 상황이 깨질 수 있습니다.

int **restrict OUT, A 및 B로 주소 된 메모리 만 겹치지 않는다고 주장합니다 (기능이 그 중 하나를 수정하지 않는다고 가정 할 때 A와 B가 겹칠 수 있음을 제외하고). 이것은 포인터의 배열을 의미합니다. N1124의 다음은 다음과 같이 말합니다.

식별자 P가 유형 (int ** Zeantrict)을 갖는 경우, 포인터 표현식 P 및 P+1은 P로 지정된 제한된 포인터 객체를 기반으로하지만 포인터 표현식 *P 및 P [1]은 그렇지 않습니다.

비유로 const, 나는 그 자격이 있다고 생각합니다 restrict 두 번 당신이 원하는 것을 주장합니다. 배열의 값 중 어느 것도 메모리를 겹치는 것을 가리키지 않습니다. 그러나 표준을 읽으면서 나는 그것이 실제로 그렇게한다는 것을 스스로 증명할 수 없습니다. 나는 "D가 T 형에 대한 제한 자격이있는 포인터로 객체 P를 지정하는 수단을 제공하는 일반 식별자의 선언으로하자"라고 생각한다. int *restrict *restrict A, 그런 다음 a [0]과 [1]은 int에 대한 제한적 자격 포인터로 지정된 객체입니다. 그러나 그것은 꽤 무거운 법인입니다.

나는 당신의 컴파일러가 실제로 그 지식으로 무엇이든 할 것인지 전혀 모른다. 분명히, 그것은 그것이 구현되었는지에 대한 문제입니다.

그래서 나는 당신이 기존의 C 2-D 배열을 통해 무엇을 얻었는지 정말로 모르겠습니다. rows * cols * sizeof(int), 그리고 색인 A[cols*row + col]. 그런 다음 제한을 한 번만 사용하면됩니다. restrict 쓰기를 통해 A와 B에서 읽을 수 있습니다. 없이 restrict, 물론, 그것은 할 수 없기 때문에 당신이하는 일을함으로써 컴파일러의 자비에 자신을 던지고 있습니다. 이중 제한에 대처할 수없는 경우 단일 제한 케이스 만 있으면 이중 간단이 최적화 비용이 듭니다.

처음에는 곱셈이 어쨌든 추가 포인터 간접보다 빠를 수 있습니다. 당신은 분명히 성능에 관심을 가지거나 제한을 전혀 사용하지 않을 것이므로, 약간 더 좋은 구문을 위해이 변경을하기 전에 성능을 공정하게 신중하게 테스트하고 몇 명이 더 많은 구문을 만들고 몇 명을 기억하지 않아도됩니다. 액세스 할 때마다 배열에 열이 있습니다.

0] [col*nrows + row]를 통해 요소에 액세스하고 있습니까?

예, 액세스 중 하나에 의해 요소가 수정되면 [0]이 [Col]를 통해 액세스하는 메모리의 별칭을 만들기 때문에. A와 B만이 제한 된 포인터 인 경우 괜찮을 것입니다.

이 기능에서 A를 수정하지 않는다고 가정하므로 실제로 별칭은 괜찮습니다. 그래도 똑같은 일을했다면 행동이 정의되지 않습니다.

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