2009-10-03 9 views
0

저는 현재 레거시 C 코드 (SPICE 변형)를 통합하는 성능이 중요한 응용 프로그램을 개발 중입니다. 다음과 같이레거시 -C C++ 통합

문제는 :

기존 C 코드의 제작자 분명히 인수 전달의 사용은 현대 시대의 위대한 악 중 하나라고 생각했다. 따라서 모든 변수 중 약 90 %가 이 전역 적으로 선언되었습니다.

시뮬레이션 목적으로 레거시 코드를 반복적으로 호출해야하며이 코드 섹션에 대한 동시 호출을 위해 스레드를 사용하면 전체 실행 시간에 도움이됩니다.

내 생각은 레거시 코드를 캡슐화하여 (기존에 g ++ 컴파일을 위해 약간 수정했다.) 많은 뮤텍스 잠금이 필요없는 레거시 코드 용 개체를 여러 개 만들 수 있도록했다. 따라서 전역 변수는 멤버 변수로 캡슐화됩니다.

이로 인해 테이블에 또 다른 문제가 발생했습니다. 레거시 코드 작성자는 또한 전역 변수의 초기화를 믿지 않았습니다. 아마도 C가 0으로 전역 변수를 초기화하는 경향이 있기 때문입니다. C++ 멤버 변수는 동일한 처리를 얻기 위해 솔기가 없습니다. 레거시 C 코드의 올바른 작동을 위해 몇 가지 변수를 0으로 초기화해야합니다. 그러나 이러한 변수를 찾는 것은 방대한 양의 전역 변수가 사용되어 매우 어렵다는 것이 입증되었습니다.

시간이 내가 레거시 C 코드를 어떤 주요도 으로 수정하는 것을 허용하지 않음을 명심하십시오.

  1. 내가 C 코드의 캡슐화는 약 90 뮤텍스 잠금 사용하는 것보다 빠를 것이라는 가정에서 수정 건가요 다음과 같이

    내 질문

    은?

  2. 초기화되지 않은 멤버 변수 사용을 쉽게 찾을 수 있습니까? (gcc는 자동 변수에 대해서만 이것을 할 수 있음을 이해함). 그래서 중요한 변수 만 초기화 할 수 있습니까?

  3. 질문 2 ... 일반 생성자 init 메서드를 사용하지 않고 모든 멤버 변수를 빠르고 깨끗하게 초기화 할 수 있습니까?

  4. 또는 (긴 샷) 거기에 프로그램 흐름을 따라갈 수있는 빠른 방법이 있습니다. 그래서 나 자신을 넘어가는 인수를 통합 할 수 있을까요?

어떤 도움을 주시면 감사하겠습니다. N.B.

+0

어느 SPICE 변형하고있는 기능? 귀하의 설명과 일치하지 않는 SPICE3 소스를 간략하게 살펴 보았습니다. –

답변

3
  1. 예. 포인터를 전달하는 객체에 상태를 놓을 수 있다면 실제로 스레드를 사용한다고 가정 할 때 잠금보다 빠를 것입니다.
  2. 아니요, 단위화된 멤버 변수를 찾는 것이 쉽지 않습니다. 본질적으로 전체 코드 분석을 수행해야합니다 (라이브러리가 있기 때문에 일반적으로 수행 할 수 없음)
  3. 모든 데이터를 구식 구조체에 넣으면 (즉, 메소드가없고 액세스 선언이 없음) , 전체 구조체를 0으로 memset() 할 수 있습니다. 이렇게하면 전역 변수가 초기화되는 것과 동일한 방식으로 초기화가 발생합니다 (C는 초기화를 보장합니다 - 0).
  4. 빠르면 "자동"을 의미하는 경우 대답은 "아니오"일 것입니다.
+0

memset을 쓰지 마십시오. 가상 테이블이없는 한 memset을 사용할 수 있습니다. 즉, 가상 함수가 아닌 한 멤버 함수를 가질 수 있으며 가상 함수가 아닌 한 상속 함수를 가질 수 있습니다. 내 충고 - 오래된 C 변수를 POD 구조체로 감싸고 클래스 내부에 넣는다. 클래스 생성자에 구조체를 memset하지만 새로운 멤버 변수를 구조체가 아닌 클래스에 직접 추가하십시오. – Steve314

+0

Steve : memset을 WRT하는 것이 가장 쉬운 방법은 그것들을 자신의 구조체에 넣고 기본 클래스로 사용하는 것입니다. – peterchen

+0

@ 스티브 : 이것은 엄격하게 정확하지 않습니다. 만약 당신이 구조체에 평범하지 않은 생성자를 가진 멤버를 가지고 있다면 struct를 memset으로 초기화해서는 안됩니다. –

0

당신은 oo-spice를 만들기보다는 포크를 사용하는 것에 대해 생각해 보셨습니까? 코드에 대한 변경이 거의 필요하지 않은 것처럼 보일 수 있습니다. 아주 작은 모델을 많이 분석하려고하지 않는 한 성능 측면에서 너무 비싸지 않을 수도 있습니다.

+0

저는 비교적 작은 회로에 대해서 많은 분석을하고 있습니다. 그래서 모든 향신료 호출에 프로세스를 사용하는 오버 헤드가 상당 할 것이라고 생각했습니다. –

+0

UNIX와 Linux에서'fork'를 사용하여 새로운 프로세스를 만드는 것은 매우 저렴합니다. 모든 코드는 이미 메모리에 있으며 메모리는 "copy on write"로 표시 될 수 있습니다. – MSalters

1

여러 스레드를 사용하려는 경우 스레드간에 공유되는 데이터를 제거하거나 잠글 필요가 있습니다. 오래된 스레드가 아닌 안전한 코드 재진입은 많은 작업과 많은 디버깅을 의미합니다. 레거시 코드를 파고 드는 데 많은 시간을 할애하지 않으면 시도하지 않겠습니다. 거대한 벌레를 열 수 있습니다.

  • -fno-common을 사용하여 g ++에서 전역에 대한 초기 0 값을 지정할 수 있습니다. gcc 매뉴얼을 참조하십시오.

  • 여러 스레드가 아닌 여러 프로세스를 사용하는 것이 좋습니다. 각 프로세스마다 자체 주소 공간이 있으므로 기존 코드에서 아무 것도 만질 필요가 없습니다. 프로세스 레벨에서 문제를 해결할 수있는 방법을 찾는 방법을 찾기가 매우 어려울 것입니다. (예 : 모든 호출에 대해 수행하지 마십시오. 논리적으로 독립적 인 문제 (예 : 한 번에 1000 개 회로의 일괄 처리)에 큰 효과가 있습니다.) 최적화하기 전에 왜 느려지는지 매우 자세히 살펴보십시오. 첫 번째 장소. 잠재적으로 제한된 보수를 위해 기존의 직렬 코드를 병렬로 만드는 것은 매우 어렵습니다. 그것이 당신이하고 싶은 것이 확실한가요?

감사합니다, 매트