2011-02-21 9 views
1

구조체에 포함 된 배열 형식에 문제가 있거나 C를 처음 사용했습니다. 나는이 컴파일 할 때구조체 배열

typedef struct { 
    double J[151][151]; 
} *UserData; 

static int PSolve(void *user_data, N_Vector solution) 
{ 
UserData data; 
data = (UserData) user_data; 

double J[151][151]; 
J = data->J; 

/* Solve a matrix equation that uses J, stored in 'solution' */ 

return(0); 
} 

내가 오류 얻을 : 다음은 내 문제의 예입니다 입력 할당 할 때 호환되지 않는 유형을 '더블 [151] [151]'더블 '유형에서 (*) 151] '

이 문제에 대한 현재의 해결 방법은 행렬 방정식을 풀 때 코드에서'J [x] [y] '를'data-> J [x] [y] '로 바꾸는 것이 었습니다. 덜 효율적인 것으로 나타났습니다.

인수의 형식과 순서를 지정하는 sundials-cvode 해결사를 사용하기 때문에 인수를 PSolve로 변경하는 것은 옵션이 아닙니다.

는 도움을 앤드류 감사

+0

가능한 중복 [C 배열 선언 및 할당?] (http://stackoverflow.com/questions/744536/c-array-declaration-and-assignment) – outis

+0

'data-> J'를 로컬 배열에 복사하는 대신? 아니면 해당 기능 내에서 수정 하시겠습니까? –

+0

나는 그 해결 방안으로 매트릭스 방정식에서 데이터 -> J [x] [y]를 읽었 음을 언급했다. 그러나이 기능은 실행 중에 수십억 번 호출됩니다. 데이터 -> J는 성능 병목 현상으로 나타납니다. 해결 방법으로 로컬 복사본을 얻으려고합니다. – Sevenless

답변

5
typedef struct { 
    double J[151][151]; 
} UserData; // This is a new data structure and should not a pointer! 

static int PSolve(void *user_data, N_Vector solution) 
{ 
UserData* data; // This should be a pointer instead! 
data = (UserData*) user_data; 

double J[151][151]; 
memcpy(J, data->J, sizeof(double) * 151 * 151); // use memcpy() to copy the contents from one array to another 

/* Solve a matrix equation that uses J, stored in 'solution' */ 

return(0); 
} 
+0

'memcpy()'에서'sizeof J'를 사용하기 만하면된다. – caf

+0

새 구조 정의를 반영하도록 코드를 업데이트했습니다. 그러나 memcpy()는 로컬 복사본이없고 J - [x] [y]를 데이터 -> J [x] [y]로 참조하는 것과 비교하여 총 계산 시간이 약 20 % 증가하므로 실행 가능한 옵션이 아닙니다. 가장 중요한 문제는 데이터 -> J가 병목 현상이있는 것처럼 보이므로 @caf가 '제한적'이라는 키워드를 사용하도록 제안 할 것입니다. – Sevenless

+0

구조체에 포인터를 만들지 말 것을 제안합니다. 왜 그런지 완전히 모르겠지만 프로그램의 다른 곳에서 작업을하지 못하게되었습니다. – Sevenless

-1

double **J으로 지역 변수 double J[151][151]를 정의하십시오.

+0

주사위가 없으면 호환되지 않는 포인터 유형에 대한 경고와 함께 컴파일되지만 실행시에는 오류가 발생합니다. 시도해 줘서 고마워. (나는 -1이 아니었다.) – Sevenless

0

배열에 할당 할 수 없습니다. 길이 151의 배열에 대한 포인터가

double (*J)[151] = data->J; 

: 당신은 당신이 당신의 코드에서 필요로하는 것은 바로이 같은 것입니다 C.

의 배열과 포인터의 차이점에 대해 찾아 볼 것이다. 또는 typedef를 사용하고 싶다면

그 자체가 아니라 데이터에 대한 포인터 만 복사하면됩니다.

편집 : 그러나 전체 답변 스레드를 보면, 그 모두가 병목 현상이있는 순수한 추측이라고 생각합니다. 예를 들어 행 아웃에 "틀린 길", 즉 현명한 열에 액세스하는 등 어디에서나 사용할 수 있습니다. 또는 메모리에서 데이터를 펌핑하는 것이 계산을 지배하는 것입니다.

어쩌면 뭔가 비린내가 있는지 알아보기 위해 컴파일러에서 생성 한 어셈블러 (옵션 -S)를 살펴 보는 것이 좋습니다.

+0

이것은 나중에 함수에서'data-> J'를 직접 사용하는 것과 다르게 행동하지는 않을 것입니다. – caf

+0

@caf인데, 간접비가 적습니다. 따라서 '데이터'가 실제로 어떻게 선언되는지에 따라 다릅니다. –

+0

@caf @ Jens-Gustedt : UserData의 typedef를 포함하고 질문의 성능 요소를 명확히하기 위해 질문을 편집했습니다. – Sevenless

2

문제의 근본 원인은 배열 형식을 C에서 직접 할당 할 수 없다는 것입니다. memcpy()을 명시 적으로 사용해야합니다 (karlphillip's answer).

그러나 사본을 수행하면 나머지 기능에서 얻는 최적화 효과가 사라질 수 있습니다. 아마도 solution 인수는 포인터이며 옵티 마이저는 user_data/datasolution 사이의 잠재적 인 별칭을 걱정합니다. 당신이 C99의 restrict 키워드를 지원하는 컴파일러가 있다면 다른 방법으로, 인수에 규정자를 사용하는 것입니다 : 이것은 그 포인터가 하지 별칭을 컴파일러를 약속

static int PSolve(void * restrict user_data, N_Vector restrict solution) 

, 허용한다 당신이 직접에 컴파일러 최적화를 희생하지 않고 data->J을 사용하십시오.

일부 컴파일러는 __restrict과 같은 맞춤법으로 restrict 키워드를 C89 모드에서 사용할 수 있도록합니다 - 자세한 내용은 컴파일러 설명서를 참조하십시오.

+0

gcc44 -c -std = C99 -I/home/matteson/sundials/include /를 사용하여 컴파일 할 때 restrict 키워드를 추가했지만 cc1 : error : 인식 할 수없는 명령 행 옵션 "-std = C99" -I/misc/linux/64/opt/pkg/matlab/R2010b/extern/include -I/기타/linux/64/opt/pkg/matlab/R2010b/simulink/include -DMATLAB_MEX_FILE -D_GNU_SOURCE -fexceptions -fPIC -fno -omit-frame-pointer -pthread -fopenmp -DMX_COMPAT_32 -O3 -DNDEBUG "het_kry.c"'gcc의 맨 페이지를 확인했는데 이것이 올바른 플래그라고합니다. – Sevenless

+1

@Sevenless : 소문자 "c"-'-std = c99'입니다. (실제로는'-std = gnu99'가 정상적인 기본값 인'gnu89'의 C99 버전입니다). – caf

+0

감사합니다, Sevenless

관련 문제