2013-07-30 2 views
1

그래서 MPI_Send/Recv에 대해 이상한 방식으로 압축해야하는 일부 구조체 데이터를 처리해야합니다.원시 데이터에 대한 포인터 연산

구조체를 연속적으로 데이터에 집어 넣었으므로 정렬 할 필요가없는 알려진 유형의 포인터로 쉽게 캐스팅 할 수있는 방법이 없습니다. 포인터 연산으로 처리해야합니다. 문제는 MPI와 일관되게 유지하기 위해이 데이터는 void *로 주어지고 void *에 대한 포인터 산술은 불법입니다.

내 질문에 주로 문체가 있습니다 : char *로 변환 한 다음 포인터 계산을 수행하는 것보다 더 나은 방법이 있습니까? void *를 가져 와서 char *로 캐스팅 할 때 효율성 문제는 무엇이겠습니까? 내 일을 처리 한 다음 void *로 다시 캐스팅하는 것은 무엇입니까? 나는 포인터 캐스트가 엄청나게 비쌀 것이라고 상상할 수 없다.

G'day and thankee 많이.

답변

3

포인터 형변환은 완전 무료입니다. 해.

형식이있는 포인터는 완전히 언어 수준 개념입니다. 하드웨어 레벨로 내려 가면 포인터는 메모리 주소로 사용되는 정수입니다.

당신은에 대한 포인터를 캐스팅 할 때이 엄격한 앨리어싱에 대해 조심해야 할 하지만 char *는 안전을 위해 정의된다, 나는 생각한다.

일부 아키텍처에서는 포인터가 "정수 일뿐"이상의 특별한 처리를하는 경우가 있지만 무시할 수 있습니다. 다른 포인터 유형 인 (예 : FDPIC)이지만 다른 사람의 문제입니다.]

+0

아, 그거 쉽지. 감사합니다. –

0

해결책은 확실합니다. 여러 번 이런 식으로했습니다 :

void handle_raw(void* data) { 
    // Use a uint8_t so pointer arithmetic is at a byte-level. 
    uint8_t* p = data;  
    uint16_t value; 

    // Read a 2-byte value at an arbitrary offset. 
    value = *(uint16_t*)(p + 0x42); 

    // Write a 2-byte value at an arbitrary offset. 
    *(uint32_t*)(p + 0x12) = 0xDEADBEEF; 
} 

물론 오프셋을 위해 상수를 사용해야하며 적절한 경계 검사를 수행해야합니다.

+0

**이 경우 ** 안전하지 않습니다. 포인터가 2 바이트 정렬되지 않으면 많은 아키텍처에서 코드가 실패합니다. 또한 타입 - 퍼닝은 에일리어싱 문제를 가지고 있습니다 : 유니온을 사용하십시오. – ams

0

버퍼를 직접 포장해야하는 특별한 이유가 있습니까? MPI 작업 전에 실제로 연속 버퍼의 데이터를 압축합니까? 그렇다면 압축과 전송 시간이 전송을 수행하는 것보다 낮아야합니다. 그렇다면, 나는 그것을 좋은 칭의라고 생각할 수 있습니다.

실제로 MPI 작업을 위해서만 연속 버퍼에 포장하는 경우 데이터를 직접 포장하지 말고 MPI 파생 데이터 형식을 사용하는 것이 더 좋습니다.

"MPI에서 파생 된 데이터 유형 예 :"과 같은 웹 검색을 수행 할 수 있으며 여기서 간단히 작성할 수있는 것보다 훨씬 더 자세한 설명을 얻을 수 있습니다.

+0

문제는 구조체가 데이터가 아니고 값의 스택으로 인덱스를 보내고 싶다는 것입니다. 그래서 포인터처럼. 이러한 것들을 곧장 보내는 것은 포인터를 보내는 것과 같이 의미가 없으므로 어떻게 든 그들을 역 참조 할 필요가 있습니다.이 스택에서 각 값의 변위가 인덱스를 포함하는 구조체의 시작에 대해 일정하지 않기 때문에 달성하기 위해 파생 데이터 유형 기계 만 사용하면 까다 롭고 불가능할 수 있습니다. –