동시성 : 디자인에 어떻게 접근하고 구현을 디버깅합니까?


37

나는 몇 년 동안 동시 시스템을 개발해 왔으며, 공식적인 교육이 부족함에도 불구하고 주제에 대해 꽤 잘 이해하고있다. Erlang 및 Go와 같이 동시성을보다 쉽게하도록 디자인 된 언어에 대해서는 최근에 인기를 얻은 몇 가지 새로운 언어가 있습니다. 동시성에 대한 접근 방식은 시스템을 확장 가능하게 만들고 여러 코어 / 프로세서 / 기계를 활용하는 방법에 대한 내 경험을 반영합니다.

그러나 나는 당신이하려는 일을 시각화하고 최소한 원래의 비전에 가깝다는 것을 확인하는 데 도움이되는 도구가 거의 없다는 것을 알았습니다. 동시 코드 디버깅은 동시성 용으로 설계되지 않은 언어 (C / C ++, C #, Java 등)로는 악몽이 될 수 있습니다. 특히 개발 환경의 한 시스템에서 쉽게 발생하는 조건을 재현하는 것은 거의 불가능합니다.

따라서 동시성 및 병렬 처리를 처리하는 시스템을 설계하는 방법은 무엇입니까? 예 :

  • 무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?
  • 오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?
  • 응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

나는 이것들 중 일부에 대한 나 자신의 대답을 가지고 있지만, 조금 더 배우고 싶습니다.

편집하다

지금까지 우리는 좋은 의견을 많이 받았습니다. 관련된 많은 기사는 매우 훌륭하며 이미 그 중 일부를 읽었습니다.

동시 프로그래밍에 대한 개인적인 경험을 통해 순차 프로그래밍과는 다른 사고 방식이 필요하다고 생각합니다. 정신적 분열은 아마도 객체 지향 프로그래밍과 절차 적 프로그래밍의 차이만큼 넓을 것입니다. 이 일련의 질문들이 체계적으로 답에 접근하기 위해 필요한 사고 과정 (즉, 이론)에 더 초점을 맞추고 싶습니다. 보다 구체적인 답변을 제공 할 때 개인적으로 겪은 일을 예로들 수 있습니다.

바운티 목표

어떻게해야하는지 말하지 마십시오. 나는 이미 그것을 통제하고 있습니다. 당신이하는 일을 말해주세요. 어떻게 말해 당신이 이러한 문제를 해결한다.


이것은 좋은 질문입니다-가능한 많은 깊이. 또한 Java의 멀티 스레드 응용 프로그램에 대한 좋은 경험을 얻었지만 자세한 내용을 알고 싶습니다.
Michael K

지금까지 몇 가지 좋은 답변이 있습니다. 누구든지 당신이이 분야에서 당신을 도와 주어야 할 것에 찌르기를 원하십니까?
Berin Loritsch

동시 코딩을위한 TotalView 디버거는 매우 유용한 도구이지만 약간의 학습 곡선이 필요합니다.- totalviewtech.com
products

로깅은 두 가지 마지막 질문에 도움이 될 수 있습니다.
Amir Rezaei

내가 찾고있는 것은 사람들의 프로세스입니다. 사용했던 도구가 부적절하지만 작업을 완료 할 수있는 영역입니다. 나는 다른 사람의 기사를 인용하는 것에 대해 덜 걱정하고 여기에서 방법론에 대해 더 관심이 있습니다.
Berin Loritsch

답변:


11

나는 몇 년 동안 동시 시스템을 개발해 왔으며, 공식적인 교육이 부족함에도 불구하고 주제에 대해 꽤 잘 이해하고있다.

내가 아는 최고의 프로그래머 중 다수는 대학을 마치지 못했습니다. 나는 철학을 공부했습니다.

C / C ++, C #, Java 등). 특히 개발 환경의 한 시스템에서 쉽게 발생하는 조건을 재현하는 것은 거의 불가능합니다.

무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?

우리는 일반적으로 1000 마일의 높은 은유로 시작하여 건축을 우리 자신 (첫 번째)과 다른 사람들 (두 번째)에게 명확히합니다.

우리는 그 문제에 직면했을 때 항상 동시 객체의 가시성을 비 동시 객체로 제한하는 방법을 찾았습니다.

최근에 나는 스칼라에서 액터를 발견했고, 나의 오래된 솔루션은 일종의 "미니 액터"이며 스칼라보다 훨씬 덜 강력하다는 것을 알았습니다. 제 제안은 거기서부터 시작하는 것입니다.

또 다른 제안은 가능한 많은 문제를 건너 뛰는 것입니다.

스칼라를 사용하면 어쨌든 훨씬 쉽습니다.

오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

여기에 실제 답변이 없습니다. 동시성에 대한 몇 가지 단위 테스트가 있으며 가능한 한 많은 응용 프로그램에 스트레스를주기위한로드 테스트 스위트가 있습니다.

응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

다시 한 번 진정한 답은 없습니다. 우리는 화이트 보드에 은유를 디자인하고 아키텍처 측면에서 충돌이 없는지 확인하려고합니다.

여기서 Arch는 Neal Ford의 정의를 의미합니다. SW Architecture는 나중에 변경하기가 매우 어려운 모든 것입니다.

프로그래밍은 순차 프로그래밍과는 다른 사고 방식이 필요하다고 생각합니다.

어쩌면 나에게는 병렬 방식으로 생각하는 것이 불가능하기 때문에 동시성 레인 사이의 충돌을 피하기 위해 병렬 사고가 필요없는 명확한 가드 레일을 사용하여 소프트웨어를 더 잘 설계하십시오.


6

나에게 모든 것은 데이터에 관한 것입니다. 데이터를 올바르게 분류하면 병렬 처리가 쉽습니다. 유지, 교착 상태 등의 모든 문제가 사라집니다.

나는 이것이 병렬화 할 수있는 유일한 방법은 아니라는 것을 알고 있지만 나에게는 가장 유용합니다.

설명하기 위해 (빠르지 않은) 이야기 :

2007 년부터 2009 년까지 대규모 재무 (주식 시장 관리) 시스템에서 작업했으며 데이터 처리량은 매우 컸습니다. 예를 들어, 클라이언트의 단일 계정 1 개에 대한 모든 계산은 평균 워크 스테이션에서 약 1 ~ 3 초가 걸렸으며 30k 개 이상의 계정이있었습니다. 매일 밤 시스템을 닫는 것은 사용자에게 큰 고통이었습니다 (일반적으로 6 시간 이상 오류 처리없이 처리).

문제를 연구 한 결과, 여러 컴퓨터간에 계산을 병렬화 할 수 있지만 이전 데이터베이스 서버 (SQL 6.5를 에뮬레이트하는 SQL 2000 서버)에는 여전히 큰 병목 현상이 발생합니다.

최소 처리 패킷은 단일 계정의 계산이며, 주요 병목 현상은 데이터베이스 서버 보존이었습니다 (우리는 "sp_who"의 여러 연결에서 동일한 처리를 기다리는 것을 볼 수있었습니다). 따라서 병렬 프로세스는 다음과 같습니다.

1) 데이터베이스를 읽거나 데이터베이스에 기록하는 단일 생산자 1 명. 여기에는 동시성이 허용되지 않습니다. 생산자는 소비자를 위해 작업 대기열을 준비했습니다. 데이터베이스는이 생산자에만 속합니다.

2) 여러 기계의 여러 소비자. 소비자 각각은 대기열에서 계산할 준비가 된 전체 데이터 패킷을 수신했습니다. 각 deqeue 조작이 동기화됩니다.

3) 계산 후 각 소비자는 데이터를 유지하기 위해 데이터를 메모리 내 동기화 된 대기열로 생산자에게 다시 보냅니다.

몇 가지 체크 포인트가 있었고 트랜잭션이 올바르게 저장되었는지 확인하는 몇 가지 메커니즘이 있었지만 (아무도 남지 않았 음) 전체 작업에 가치가있었습니다. 결국 10 대의 컴퓨터 (생산자 / 대기 컴퓨터)에 분산 된 계산으로 전체 시스템의 종료 시간이 15 분으로 단축되었습니다.

동시성 관리가 좋지 않은 SQL 6.5로 인한 유지 문제를 해결하는 것만으로도 큰 이점이있었습니다. 나머지는 거의 선형 적이며 "그리드"에 추가 된 각각의 새 컴퓨터는 데이터베이스에서 순차적 인 읽기 / 쓰기 작업의 "최대 효율성"에 도달 할 때까지 처리 시간을 단축했습니다.


2

멀티 스레딩 환경에서 작업하는 것은 어렵고 코딩 규칙이 필요합니다. 잠금, 잠금 해제, 전역 변수 액세스 등에 대한 올바른 지침을 따라야합니다.

당신의 질문에 하나씩 대답하려고 노력하겠습니다

* How do you figure out what can be made concurrent vs. what has to be sequential?

동시성 사용

1) 폴링 :-지속적으로 무언가를 폴링하거나 정기적으로 업데이트를 보내려면 스레드가 필요합니다. (심장 비트와 같은 개념으로, 일정한 간격으로 일부 데이터를 중앙 서버에 전송하여 살아 있다고 말합니다.)

2) I / O가 많은 작업을 병렬로 수행 할 수 있습니다. 가장 좋은 예는 로거입니다. 로거 스레드는 별도의 스레드 일 수 있습니다.

3) 다른 데이터에 대한 유사한 작업. 다른 데이터에서 발생하지만 본질적으로 매우 유사한 작업이 있으면 다른 스레드가이를 수행 할 수 있습니다. 가장 좋은 예는 서버 요청입니다.

그리고 물론 응용 프로그램에 따라 이와 같은 많은 다른 사람들이 있습니다.

* How do you reproduce error conditions and view what is happening as the application executes?

로그에서 로그 및 디버그 인쇄 사용 스레드 ID도 기록하여 각 스레드에서 무슨 일이 일어나고 있는지 확인할 수 있습니다.
오류 조건을 생성하는 한 가지 방법은 문제가 발생한다고 생각되는 곳에 의도적 인 지연 (디버그 코드)을 설정하고 해당 스레드를 강제로 중지하는 것입니다. 디버거에서도 비슷한 작업을 수행 할 수 있지만 지금까지는 수행하지 않았습니다.

* How do you visualize the interactions between the different concurrent parts of the application?

누가 무엇을 언제 잠그는 지 누가 잠금을 시도했는지 알 수 있도록 로그를 자물쇠에 넣으십시오. 앞에서 말했듯이 스레드 ID를 로그에 넣어 각 스레드에서 수행되는 작업을 이해하십시오.

이것은 멀티 스레드 응용 프로그램에서 약 3 년 동안 일한 조언이며 도움이되기를 바랍니다.


2
  • 무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?

먼저 응용 프로그램 (또는 구성 요소)이 동시 처리의 이점을 얻을지 또는 평신도의 관점에서 이점을 볼 수 있는지 여부를 먼저 묻습니다. 병목 현상은 어디에 있습니까? 동시성이 항상 작동하기 위해 필요한 투자에 이점을 제공하는 것은 아닙니다. 그것이 후보처럼 보이는 경우, 상향식으로 작업 할 것입니다-가장 효율적으로 작업을 수행 할 수있는 가장 큰 작업이나 작업 집합을 찾으려고 노력합니다. 운영- 배우를 찾고 있습니다.

Erlang과 함께 작업 비동기 메시지 전달과 동시성에 대한 액터 모델을 사용한다는 개념은 직관적이고 효과적이며 깨끗합니다.

의 오프 이해 배우의 동시성

액터 모델은 몇 가지 주요 원칙으로 구성됩니다.

  • 공유 상태가 없습니다
  • 경량 프로세스
  • 비동기 메시지 전달
  • 수신 메시지를 버퍼링하는 사서함
  • 패턴 일치를 사용한 메일 함 처리

액터는 기능을 실행하는 프로세스입니다. 여기서 프로세스는 가벼운 사용자 공간 스레드입니다 (일반적인 헤비급 운영 체제 프로세스와 혼동하지 마십시오). 액터는 상태를 공유하지 않으므로 공유 데이터에 액세스하기 위해 잠금을 위해 경쟁 할 필요가 없습니다. 대신 액터는 변경할 수없는 메시지를 보내 데이터를 공유합니다. 변경 불가능한 데이터는 수정할 수 없으므로 읽기에는 잠금이 필요하지 않습니다.

Erlang 동시성 모델은 잠금 및 공유 데이터보다 이해하고 디버그하기가 더 쉽습니다. 로직이 분리되는 방식으로 메시지를 전달하여 구성 요소를 쉽게 테스트 할 수 있습니다.

동시 시스템을 사용하면 여러 스레드가 데이터를 가져와 간단한 작업을 수행하고 반복하거나 대기열로 다시 밀어 넣는 대기열이 어떤 언어로도 디자인이 작동하는 방식과 거의 같습니다. Erlang은 부수적 인 데이터 구조를 시행하여 부작용을 방지하고 새로운 스레드 생성의 비용과 복잡성을 줄입니다.

이 모델은 Erlang 독점이 아니며 Java 및 .NET 세계에서도이를 만드는 방법이 있습니다 .CCR ( Concurrency and Coordination Runtime)Relang (Jetlang for Java도 있음)을 살펴 보겠습니다.

  • 오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

내 경험상, 내가 할 수있는 유일한 것은 모든 것을 추적 / 로깅한다는 약속입니다. 모든 프로세스 / 스레드에는 식별자가 필요하며 새로운 각 작업 단위에는 상관 관계 ID가 있어야합니다. 로그를 살펴보고 처리 된 내용과시기를 정확하게 추적 할 수 있어야합니다.이를 제거 할 수있는 마법은 없습니다.

  • 응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

위의 내용은 추악하지만 작동합니다. 내가 할 유일한 다른 것은 UML 시퀀스 다이어그램을 사용하는 것입니다. 물론 이것은 디자인 타임에 있습니다. 그러나 컴포넌트를 사용하여 원하는 방식으로 말하는지 확인할 수 있습니다.


1

-제 답변은 MS / Visual Studio에 따라 다릅니다.

무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?

그것은 도메인 지식을 취할 것이며, 그것을 다루기 위해 여기에 담요 진술이 없을 것입니다.

오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

많은 로깅, 프로덕션 애플리케이션에서 로깅을 설정하기 위해 프로덕션 애플리케이션에서 로깅을 켜거나 끌 수 있습니다. VS2010 Intellitrace 가이를 도울 수는 있지만 아직 사용하지 않았습니다.

응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

나는 이것에 대한 좋은 대답이 없으며, 그것을보고 싶어합니다.


로깅은 코드 실행 방식을 변경하므로 표시되지 않은 오류가 발생할 수 있습니다.
Matthew 읽기

1

C가 동시성을 위해 설계되지 않았다는 귀하의 진술에 동의하지 않습니다. C는 일반적인 시스템 프로그래밍을 위해 설계되었으며 중요한 결정을 내릴 때 강점을 가지고 있으며 앞으로도 계속 그렇게 할 것입니다. 최선의 결정이 C를 사용하지 않는 경우에도 마찬가지입니다. 또한 C의 동시성은 디자인이 복잡 할 때만 어렵습니다.

최선을 다해 궁극적으로 실질적인 잠금없는 프로그래밍이 현실이 될 수 있다는 생각으로 잠금을 구현하려고 시도 합니다. 잠금은 상호 배제를 의미하는 것이 아니라 중재가 필요없는 안전한 동시성을 구현하는 프로세스를 의미합니다. 실제로는 구현하는 것보다 이식하기 쉬운 것을 의미합니다. 나는 공식적인 CS 교육도 거의 없지만, 내가 원하는 것을 허락한다고 생각합니다 :)

그 후, 내가 겪는 대부분의 버그는 상대적으로 얕아 지거나 완전히 마음이 흔들리면서 술집으로 퇴각합니다. 이 펍은 프로그램을 프로파일 링하면 내가 찾으려고하는 것과 관련이없는 추가 인종을 노출시키기에 충분히 느려질 때만 매력적인 옵션이됩니다.

다른 사람들이 지적했듯이, 설명하는 문제는 도메인에 따라 다릅니다. 가능한 한 언제든지 (프로세스 외부) 중재가 필요한 경우를 피할 수 있도록 최선을 다하고 있습니다. 그것이 당당한 고통 인 것처럼 보이면 여러 스레드 또는 프로세스에 동시 및 직렬화되지 않은 액세스 권한을 부여하는 옵션을 다시 평가합니다.

그런 다음 다시 '분산'을 던져 중재가 필수가됩니다. 구체적인 예가 있습니까?


내 진술을 명확히하기 위해 C는 동시성을 위해 특별히 설계되지 않았습니다. 이는 동시성을 염두에두고 명시 적으로 설계된 Go, Erlang 및 Scala와 같은 언어와 대조적입니다. 나는 당신이 C와 동시성을 할 수 없다고 말하고 싶지 않았습니다.
Berin Loritsch

1

오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

내 경험을 바탕으로이 두 가지 측면에 대한 답은 다음과 같습니다.

분산 추적

분산 추적은 시스템의 각 개별 동시 구성 요소에 대한 타이밍 데이터를 캡처하여 그래픽 형식으로 표시하는 기술입니다. 동시 실행의 표현은 항상 인터리브되어 실행중인 것과 그렇지 않은 것을 확인할 수 있습니다.

분산 추적은 원래 분산 시스템에서 발생하며, 정의상 비동기식이며 동시성이 높습니다. 분산 추적 기능이있는 분산 시스템을 통해 다음을 수행 할 수 있습니다.

a) 중요한 병목 현상을 식별합니다. b) 응용 프로그램의 이상적인 '실행'에 대한 시각적 표현을 얻습니다 .c) 동시 동작이 실행되고 있는지 파악하고 d) 시스템 (SLA가 강한 경우 매우 중요).

그러나 분산 추적의 결과는 다음과 같습니다.

  1. 네트워크를 통해 잠재적으로 실행 및 제출하기 위해 더 많은 코드로 변환되므로 모든 동시 프로세스에 오버 헤드가 추가됩니다. 경우에 따라 이러한 오버 헤드는 매우 중요합니다. Google조차도 사용자 경험을 망치지 않기 위해 모든 요청의 작은 하위 집합에서만 추적 시스템 인 Dapper 만 사용합니다.

  2. 서로 다른 많은 도구가 존재하지만 모두 서로 상호 운용 가능한 것은 아닙니다. 이것은 OpenTracing과 같은 표준으로 다소 개선되었지만 완전히 해결되지는 않았습니다.

  3. 공유 리소스 및 현재 상태에 대해서는 아무 것도 알려주지 않습니다 . 응용 프로그램 코드와 그래프에 표시되는 내용에 따라 추측 할 수 있지만이 점에서 유용한 도구는 아닙니다.

  4. 현재 도구는 여분의 메모리와 스토리지가 있다고 가정합니다. 제약 조건에 따라 시계열 서버 호스팅 비용이 저렴하지 않을 수 있습니다.

오류 추적 소프트웨어

Sentry는 주로 가장 널리 사용되는 도구이기 때문에 Sentry와 주로 연결되며 Sentry 하이 재크 런타임 실행과 같은 오류 추적 소프트웨어는 중앙 서버에 발생한 오류의 스택 추적을 동시에 전달합니다.

동시 코드에서 이러한 전용 소프트웨어의 장점 :

  1. 중복 오류는 중복되지 않습니다 . 즉, 하나 이상의 동시 시스템에 동일한 예외가 발생하면 Sentry는 사고 보고서 를 증가 시키지만 사고 사본 2 부를 제출하지는 않습니다.

이는 수많은 동시 오류 보고서를 거치지 않고 어떤 종류의 동시 시스템에서 어떤 종류의 오류가 발생하는지 파악할 수 있음을 의미합니다. 분산 시스템에서 전자 메일 스팸을 겪은 적이 있다면 기분이 어떻습니까?

동시 시스템의 여러 측면에 '태그'를 지정할 수도 있습니다 (이것은 정확히 하나의 스레드에 인터리브 된 작업이 없다고 가정하지만 스레드는 단순히 작업간에 효율적으로 점프하지만 여전히 이벤트 핸들러를 처리해야하기 때문에 기술적으로는 동시 적이 지 않습니다. 태그로 오류를 분석하십시오.

  1. 이 오류 처리 소프트웨어를 수정하여 런타임 예외에 대한 추가 세부 사항을 제공 할 수 있습니다. 프로세스에는 어떤 오픈 리소스가 있습니까? 이 프로세스가 보유한 공유 리소스가 있습니까? 어떤 사용자가이 문제를 경험 했습니까?

이를 통해 꼼꼼한 스택 추적 (및 파일의 축소 버전을 제공해야하는 경우 소스 맵)을 통해 많은 시간이 걸리는 문제를 쉽게 확인할 수 있습니다.

  1. (엔트리 특정) 시스템의 테스트 실행을 위해 별도의 Sentry보고 대시 보드를 가질 수있어 테스트시 오류를 포착 할 수 있습니다.

이러한 소프트웨어의 단점은 다음과 같습니다.

  1. 모든 것과 마찬가지로 대량으로 추가합니다. 예를 들어 그러한 시스템을 내장 하드웨어에 원하지 않을 수 있습니다. 유휴 시스템에서 수백 번의 실행을 샘플링하거나 수행하지 않고 간단한 실행을 비교하여 이러한 소프트웨어를 시범 적으로 실행하는 것이 좋습니다.

  2. 이러한 시스템 중 상당수가 암시 적으로 예외를 포착하는 데 의존하고 모든 언어에 강력한 예외가있는 것은 아니므로 모든 언어가 동일하게 지원되는 것은 아닙니다. 즉, 많은 시스템에 대한 클라이언트가 있습니다.

  3. 이러한 시스템 중 상당수가 본질적으로 비공개 소스이므로 보안 위험이 발생할 수 있습니다. 그러한 경우, 조사 할 때 실사를 수행하거나 원하는 경우 직접 조사하십시오.

  4. 필요한 정보를 항상 제공하지는 않습니다. 이것은 가시성을 추가하려는 모든 시도에서 위험합니다.

  5. 이러한 서비스는 대부분 동시 웹 응용 프로그램 용으로 설계되었으므로 모든 도구가 사용 사례에 완벽하지는 않습니다.

요약 : 가시성을 갖는 것은 동시 시스템에서 가장 중요한 부분입니다. 위에서 설명한 두 가지 방법은 하드웨어 및 데이터에 대한 전용 대시 보드와 함께 특정 시점에 시스템을 획기적인 그림으로 볼 수 있도록 업계 전반에 걸쳐 해당 측면을 해결하는 데 널리 사용됩니다.

몇 가지 추가 제안

끔찍한 방법으로 동시 문제를 해결하려고 시도한 사람들이 코드를 수정하는 것보다 더 많은 시간을 보냈습니다. 매번 다음 사항이 개발자 경험을 크게 향상시킬 수있는 사례를 발견했습니다 (사용자 경험만큼 중요합니다).

  • 유형에 의존하십시오 . 입력은 코드의 유효성을 검사하기 위해 존재하며 런타임시 추가 가드로 사용할 수 있습니다. 입력이 존재하지 않는 경우 어설 션 및 적절한 오류 처리기를 사용하여 오류를 포착하십시오. 동시 코드 에는 방어 코드 가 필요 하며 유형은 사용 가능한 최상의 종류의 검증 역할을합니다.

    • 컴포넌트 자체뿐만 아니라 코드 컴포넌트 사이의 링크를 테스트 하십시오. 이것을 모든 구성 요소 사이의 모든 링크를 테스트하는 완전한 통합 테스트와 혼동하지 말고 최종 상태의 글로벌 유효성 검사 만 찾습니다. 이것은 오류를 잡는 끔찍한 방법입니다.

적절한 링크 테스트 는 한 구성 요소가 다른 구성 요소 와 격리 되어 통신 할 때 받은 메시지와 보낸 메시지가 예상 한 것과 같은지 확인합니다. 통신을 위해 공유 서비스에 의존하는 둘 이상의 구성 요소가있는 경우 구성 요소를 모두 스핀 업하고 중앙 서비스를 통해 메시지를 교환하게하고 결국에는 예상 한 결과를 얻는 지 확인하십시오.

많은 구성 요소를 포함하는 테스트를 구성 요소 자체 테스트와 각 구성 요소가 어떻게 통신하는지 테스트하면 코드의 유효성에 대한 신뢰도가 높아집니다. 이러한 엄격한 테스트를 통해 서비스 간 계약을 시행 할 수있을뿐만 아니라 서비스가 한 번에 실행될 때 발생하는 예기치 않은 오류를 포착 할 수 있습니다.

  • 올바른 알고리즘을 사용하여 응용 프로그램 상태를 확인하십시오. 모든 작업자가 작업을 완료하기를 기다리는 마스터 프로세스가 있고 모든 작업자가 완전히 완료된 경우에만 다음 단계로 이동하려는 경우와 같은 간단한 것들에 대해 이야기하고 있습니다. Safra의 알고리즘과 같은 알려진 방법론이 존재하는 종료.

이러한 도구 중 일부는 언어와 함께 번들로 제공됩니다. 예를 들어 Rust는 코드가 컴파일 타임에 경쟁 조건을 갖지 않도록하고 Go는 컴파일 타임에도 실행되는 내장 교착 상태 탐지기를 갖추고 있습니다. 문제가 발생하기 전에 문제를 잡을 수 있다면 항상 승리입니다.

일반적인 경험 법칙 : 동시 시스템의 장애에 대한 설계 . 공통 서비스가 중단되거나 중단 될 것으로 예상하십시오. 단일 시스템의 동시 코드는 공유 로그 파일, Redis 서버, 망할 MySQL 서버와 같은 외부 종속성을 사용하여 언제라도 사라지거나 제거 할 수 있습니다. .

이 작업을 수행하는 가장 좋은 방법은 응용 프로그램 상태를 수시로 확인하는 것입니다. 각 서비스에 대한 상태를 확인하고 해당 서비스 소비자에게 상태가 잘못되었음을 알리는 것입니다. Docker와 같은 최신 컨테이너 도구는이 작업을 잘 수행하므로 사물을 샌드 박스로 사용해야합니다.

무엇을 동시에 만들 수 있고 무엇을 순차적으로 만들 수 있는지 어떻게 알 수 있습니까?

동시성이 높은 시스템에서 작업하면서 배운 가장 큰 교훈 중 하나는 다음과 같습니다 . 충분한 메트릭을 가질 수 없습니다 . 측정 항목은 애플리케이션에서 모든 것을 절대적으로 구동해야합니다. 모든 것을 측정하지 않으면 엔지니어가 아닙니다.

측정 항목이 없으면 몇 가지 매우 중요한 작업을 수행 할 수 없습니다.

  1. 시스템 변경으로 인한 차이점을 평가하십시오. 튜닝 노브 A로 인해 메트릭 B가 올라가고 메트릭 C가 내려 졌는지 알 수없는 경우, 사람들이 시스템에서 예기치 않게 악성 코드를 푸시 할 때 시스템을 수정하는 방법을 모릅니다 (및 시스템에 코드를 푸시 함) .

  2. 일을 개선하기 위해 다음에해야 할 일을 이해하십시오. 응용 프로그램의 메모리가 부족하다는 것을 알기 전까지는 더 많은 메모리를 확보해야하는지 또는 서버용으로 더 많은 디스크를 구입해야하는지 식별 할 수 없습니다.

측정 항목은 매우 중요하고 필수적이므로 시스템에 필요한 사항에 대해 생각하기 전에 측정 할 대상을 계획하기위한 의식적인 노력을 기울였습니다. 사실, 통계는 내가 믿는 너무 중요하다 그들은 이 질문에 대한 정답입니다 만 순차적 또는 당신이 때 동시에 할 수 무엇인지 측정 프로그램의 비트가 무엇을하고 있는지를. 적절한 디자인은 추측이 아닌 숫자를 사용합니다.

그러나 몇 가지 규칙이 있습니다.

  1. 순차적은 의존성을 의미합니다. 하나가 어떤 방식으로 다른 것에 의존하는 경우 두 프로세스는 순차적이어야합니다. 종속성이없는 프로세스는 동시에 진행되어야합니다. 그러나 다운 스트림 프로세스가 무기한 대기하지 못하게하는 장애 조치 스트림을 처리하는 방법을 계획하십시오.

  2. I / O 바운드 작업을 동일한 코어의 CPU 바운드 작업과 혼합하지 마십시오. 예를 들어, 동일한 스레드에서 10 개의 동시 요청을 시작하고 들어오는 즉시 요청을 스크랩하며 500 개로 확장 할 것으로 예상하는 웹 크롤러를 작성하지 마십시오. I / O 요청은 대기열에 병렬로 이동하지만 CPU는 여전히 직렬로 통과합니다. (이 단일 스레드 이벤트 중심 모델은 널리 사용되는 모델이지만이 측면으로 인해 제한되어 있습니다.이를 이해하기보다는 사람들이 단순히 손을 잡고 노드가 확장되지 않는다고 설명합니다.)

단일 스레드는 많은 I / O 작업을 수행 할 수 있습니다. 그러나 하드웨어의 동시성을 완전히 사용하려면 모든 코어를 함께 차지하는 스레드 풀을 사용하십시오. 위의 예에서 CPU 작업을 위해 5 개의 Python 프로세스 (각각 6 코어 시스템에서 코어를 사용할 수 있음)를 시작하고 I / O 작업을위한 6 번째 Python 스레드는 생각보다 훨씬 빠르게 확장됩니다.

CPU 동시성을 활용하는 유일한 방법은 전용 스레드 풀을 사용하는 것입니다. 단일 스레드는 종종 많은 I / O 바운드 작업에 충분합니다. 이것이 Nginx와 같은 이벤트 중심 웹 서버가 Apache보다 I / O 바운드 작업을 강화하고 요청 당 프로세스를 시작하는 Apache보다 더 나은 (순수하게 I / O 바운드 작업을 수행하는) 이유이지만 Node를 사용하여 수행하는 이유 병렬로받은 수만 개의 GPU 계산은 끔찍한 아이디어입니다.


0

검증 프로세스의 경우 대규모 동시 시스템을 설계 할 때는 LTSA 레이블이 지정된 전환 시스템 분석기를 사용하여 모델을 테스트하는 경향이 있습니다. 그것은 병행 분야의 베테랑이자 지금 제국의 컴퓨팅 책임자 인 내 오래된 교사에 의해 개발되었습니다.

동시에 할 수있는 것과 할 수없는 것을 해결하는 한, 프로젝트 관리에서와 마찬가지로 중요한 섹션에 대한 일정 다이어그램을 그리는 경향이 있지만, 믿을 수있는 정적 분석기가 있습니다. 그런 다음 동일한 작업을 반복적으로 수행하는 섹션을 식별하십시오. 빠른 경로는 병렬 처리의 이점이있는 영역이기 때문에 루프를 찾는 것입니다.


0

무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?

여러분이 작성하는 거의 모든 것이 동시성을 활용할 수 있습니다. 특히 "정복을 결정하십시오"사용 사례. 더 좋은 질문은 무엇 을 동시에해야합니까?

C # 의 Joseph Albahari의 스레딩에는 5 가지 일반적인 용도가 나와 있습니다.

멀티 스레딩에는 많은 용도가 있습니다. 가장 일반적인 내용은 다음과 같습니다.

반응 형 사용자 인터페이스 유지

병렬 "작업자"스레드에서 시간 소모적 인 작업을 실행하면 기본 UI 스레드는 키보드 및 마우스 이벤트를 계속 처리 할 수 ​​있습니다.

차단 된 CPU를 효율적으로 사용

멀티 스레딩은 스레드가 다른 컴퓨터 나 하드웨어에서 응답을 기다리는 경우에 유용합니다. 작업을 수행하는 동안 하나의 스레드가 차단되는 동안 다른 스레드는 그렇지 않은 컴퓨터를 활용할 수 있습니다.

병렬 프로그래밍

집중적 인 계산을 수행하는 코드는 "분할 및 정복"전략으로 작업 부하가 여러 스레드간에 공유되는 경우 멀티 코어 또는 다중 프로세서 컴퓨터에서 더 빠르게 실행될 수 있습니다 (5 부 참조).

투기 적 실행

멀티 코어 시스템에서는 수행해야 할 사항을 예측 한 다음 미리 수행하여 성능을 향상시킬 수 있습니다. LINQPad는이 기술을 사용하여 새 쿼리 생성 속도를 높입니다. 변형은 모두 동일한 작업을 해결하는 여러 가지 다른 알고리즘을 병렬로 실행하는 것입니다. 첫 번째 "승리"를 완료하는 것 중 어느 것이 어떤 알고리즘이 가장 빨리 실행 될지 미리 알 수 없을 때 효과적입니다.

요청을 동시에 처리 할 수 ​​있도록 허용

서버에서 클라이언트 요청이 동시에 도착할 수 있으므로 병렬로 처리해야합니다 (ASP.NET, WCF, 웹 서비스 또는 원격을 사용하는 경우 .NET Framework는이를 위해 자동으로 스레드를 생성합니다). 이는 클라이언트에서 유용 할 수 있습니다 (예 : 피어 투 피어 네트워킹 또는 사용자의 여러 요청 처리).

위의 방법 중 하나를 시도하지 않는다면 아마도 그것에 대해 열심히 생각하는 것이 좋습니다.

오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

.NET을 사용 중이고 사용 사례를 작성한 경우 CHESS 를 사용하면 특정 스레드 인터리빙 조건을 재현하여 수정 사항을 테스트 할 수 있습니다.

응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

상황에 따라 다릅니다. 작업자 시나리오의 경우 관리자 직원을 생각합니다. 관리자는 부하 직원에게 무언가를하도록 지시하고 상태 업데이트를 기다립니다.

동시에 관련되지 않은 작업의 경우 별도의 차선에서 엘리베이터 또는 자동차를 생각합니다.

동기화를 위해 때때로 신호등이나 턴 스타일을 생각합니다.

또한 C # 4.0을 사용하는 경우 작업 병렬 라이브러리를 살펴볼 수 있습니다.


0

이 질문에 대한 나의 대답은 다음과 같습니다.

  • 무엇을 동시에 할 수 있는지와 순차적이어야하는 것을 어떻게 알 수 있습니까?

먼저 사람들이 동시성에 대한 아이디어로 빠져 나왔지만 항상 해결하려는 문제에 대해 항상 생각하지는 않는다는 것을 알았 기 때문에 동시성을 사용해야하는 이유를 알아야합니다.

대기열, 워크 플로 등과 같은 실제 상황을 시뮬레이션해야하는 경우 동시 접근 방식을 사용해야합니다.

이제 나는 그것을 사용해야한다는 것을 알고 있습니다. 거래를 분석하는 시간입니다. 프로세스가 많으면 통신 오버 헤드에 대해 생각할 수 있지만 새로운 경우에는 동시 솔루션이 없을 수 있습니다 (문제가있는 경우 다시 활성화하십시오) 그래서.)

  • 오류 조건을 어떻게 재현하고 응용 프로그램이 실행될 때 어떤 일이 발생하는지 확인합니까?

나는이 문제에 대해 전문가가 아니지만 동시 시스템의 경우 이것이 올바른 접근법이 아니라고 생각합니다. 중요한 영역에 대한 4 가지 교착 상태 요구 사항을 찾아 이론적 접근 방식을 선택해야합니다.

  1. 비 선점
  2. 기다려
  3. 상호 배제
  4. 원형 체인

    • 응용 프로그램의 서로 다른 동시 부분 간의 상호 작용을 어떻게 시각화합니까?

먼저 상호 작용에 참여한 사람을 식별 한 다음 어떻게 의사 소통하고 누구와 의사 소통을합니까? 마지막으로 그래프와 상호 작용 다이어그램을 통해 시각화 할 수 있습니다. 내 오래된 오래된 화이트 보드는 다른 종류의 미디어로 이길 수 없습니다.


0

나는 무딘거야. 나는 도구를 좋아한다. 나는 많은 도구를 사용합니다. 첫 단계는 의도 된 흐름의 경로를 제시하는 것입니다. 다음 단계는 가치가 있는지 또는 필요한 정보 흐름이 코드 직렬을 너무 자주 렌더링하는지 알아 내려고 시도하는 것입니다. 그런 다음 간단한 모델을 작성하고 작성해 보겠습니다. 이것들은 조잡한 이쑤시개 조각에서 파이썬의 간단한 유사한 예에 이르기까지 다양합니다. 다음으로, 나는 작은 세마포어 책과 같이 내가 좋아하는 두 권의 책을 살펴보고 누군가가 이미 내 문제에 대한 더 나은 해결책을 찾았는지 확인합니다.

그런 다음 코딩을 시작합니다.
농담이야 먼저 조금 더 연구하십시오. 나는 동료 해커와 함께 앉아 프로그램의 예상 실행 수준을 높은 수준으로 걷는 것을 좋아합니다. 질문이 나오면 더 낮은 단계로 나아갑니다. 다른 사람이 솔루션을 유지하기에 충분한 솔루션을 이해할 수 있는지 알아내는 것이 중요합니다.

마지막으로 코딩을 시작합니다. 나는 그것을 매우 간단하게 유지하려고 노력합니다. 코드 경로만으로도 멋진 것은 아닙니다. 가능한 적은 상태로 이동하십시오. 쓰기를 피하십시오. 쓰기와 충돌 할 수있는 읽기를 피하십시오. 무엇보다도 쓰기와 충돌 할 수있는 쓰기는 피하십시오. 당신이 긍정적으로 독성이있는 수를 가지고 있고, 아름다운 해결책이 갑자기 캐시 스 래싱 직렬 접근 방식에 지나지 않는다는 것을 쉽게 알 수 있습니다.

규칙은 가능한 한 프레임 워크를 사용하는 것입니다. 좋은 동기화 데이터 구조 나 신의 금지 된 실제 동기화 기본 요소와 같은 기본 스레딩 구성 요소를 직접 작성하는 경우 거의 모든 다리를 날려 버릴 것입니다.

마지막으로 도구. 디버깅은 매우 어렵습니다. 리눅스에서는 valgrind \ callgrind를 PIN과 함께 사용하고 병렬 스튜디오는 Windows에서 사용합니다. 이 물건을 직접 손으로 디버깅하지 마십시오. 당신은 아마 할 수 있습니다. 그러나 당신은 아마 당신이하지 않았 으면 좋겠다. 10 시간 동안 강력한 도구를 익히고 몇 가지 좋은 모델을 사용하면 수백 시간을 절약 할 수 있습니다.

무엇보다도 점진적으로 작업하십시오. 신중하게 작업하십시오. 피곤할 때 동시 코드를 작성하지 마십시오. 배가 고플 때는 쓰지 마십시오. 실제로, 피할 수 있다면 작성하지 마십시오. 동시성은 어렵고 기능으로 나열하는 많은 앱이 종종 유일한 기능으로 제공되는 것으로 나타났습니다.

요약 :
시작 :
생각
토크
테스트
쓰기가 단순히
읽기
시험
쓰기
디버그
GOTO 시작

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.