RTOS에서 대기열 교체


12

태스크 간 통신 또는 RTOS의 두 태스크간에 데이터를 공유하기 위해 큐를 사용합니다. 그러나 큐의 문제점은 느리다는 것입니다. 버퍼에서 데이터를 복사 한 다음 Mutex 처리 및 데이터 전송으로 복사합니다. 대용량 데이터를 전송해야한다면 짜증이납니다. 또 다른 문제는 여러 작업에서 동일한 대기열에 액세스하는 경우입니다. 그런 다음 그림은 다음과 같습니다 .- 먼저 대기열에 액세스하기 위해 대기 한 다음 대기열 내부 뮤텍스 처리 및 데이터 전송.

이것은 시스템의 오버 헤드를 증가시킵니다. 대기열을 효율적으로 대체 할 수있는 것은 무엇입니까 ?

(이 질문은 우리가 사용하는 RTOS와 무관합니다. 대부분의 RTOS는 이러한 방식으로 대기열을 처리합니다)


여러 작업에서 액세스 한 대기열이란 무엇입니까? 대기열에 게시하거나 대기열에서 읽는 것을 의미합니까? 최소한의 오버 헤드로 여러 작업을 대기열에 게시 할 수 있어야합니다. RTOS는 뮤텍스를 처리하여 포스트가 원자 연산이되도록해야합니다. 작업의 99 %를 위해 큐에 대기하고 메시지를 처리하는 루프가 있어야합니다. 대기열은 일반적으로 하나의 작업 만 읽을 수 있습니다. 디자인과 큐를 바꾸는 대신 큐를 사용하는 방법을 살펴보아야 할 것입니다.
에릭

@ 에릭 : 죄송합니다! 나는 당신이 언급 한 메커니즘을 사용하고 있습니다 .... 나는 다른 말을하고 싶었고 다른 것을 썼다 .... 나는 그것을 편집 할 것이다! 실수를 지적 해 주셔서 감사합니다! 코드에서 큐 액세스를 기다리고 있습니다!
Swanand

답변:


7

대기열은 작업 간 통신을위한 스레드 안전 트랜잭션 모델이므로 이러한 방식으로 작동합니다. 덜 엄격한 체계에서 데이터 손상 및 / 또는 소유권 문제가 발생할 위험이 있습니다.

데이터를 메모리의 버퍼에 복사 한 다음 큐 요소와 함께 포인터를 전달하거나 큐 요소 자체의 모든 데이터를 전달하려고합니까? 포인터를 전달하지 않으면 대기열 요소를 통해 한 번에 1 바이트를 전달하는 대신 성능이 향상됩니다.


2
나는 똑같은 말을하려고했다. 대기열의 데이터에 포인터를 전달하면 속도를 높일 수 있지만 데이터를 사용하고 변경하려는 두 개의 스레드로 끝나지 않도록하십시오.
Kortuk

@Kortuk이 말했듯이 "데이터를 사용하고 변경하려고하는 두 개의 스레드로 끝나지 않도록하십시오"... 오버 헤드가 증가한다는 것을 의미합니다 ... 많은 처리를 원하지 않습니다! :(
Swanand

따라서 대기열에 대한 대체품은 없습니다 ... Data Queue 대신 Pointer Queue를 사용해야합니다!
Swanand

1
@Swanand 대기열이 단방향 일뿐 (즉, 두 작업에서 동일한 대기열을 읽지 않음)으로 응용 프로그램을 계획하고 포인터에 저장된 데이터를 즉시 처리 한 다음 해제하면 데이터 공유에 문제가 없어야합니다. 데이터를 안정적으로 앞뒤로 전달하기 위해 여러 큐를 작성해야 할 수 있으므로 오버 헤드가 증가하지만 이는 멀티 태스킹 환경에서 비즈니스를 수행하는 비용입니다.
AngryEE

7

쉬운 방법 중 하나는 큐에있는 데이터에 포인터를 놓고 포인터를 사용하여 데이터를 소비하는 것입니다.

다음과 같은 사항을 확인해야하므로 성능을 위해 안전을 거래해야합니다.

  1. 소비자가 데이터를 소비 할 때까지 버퍼는 계속 유효합니다.
  2. 누군가 버퍼 할당을 해제

동적으로 할당 된 메모리를 사용하지 않는 경우 할당을 해제 할 필요는 없지만 데이터를 사용하기 전에 메모리 영역을 다시 사용하지 않아야합니다.


6

단일 생산자 / 단일 소비자 사례에 대해 잠금없는 대기 행렬을 구현할 수 있으며, 종종 다중 생산자 또는 다중 소비자 대기 행렬 수를 최소화하도록 소프트웨어를 설계 할 수 있습니다.

잠금이없는 큐는 다음과 같이 구성 될 수 있습니다. 통신 할 요소의 배열과 두 개의 정수를 할당하여 헤드와 테일이라고합니다. Head는 배열에 대한 인덱스이며 다음 항목이 추가됩니다. Tail은 배열에 대한 색인이며 다음 항목을 제거 할 수 있습니다. 생산자 작업은 H 및 T를 읽고 항목을 추가 할 여지가 있는지 확인합니다. 소비자 작업은 H와 T를 읽고 사용 가능한 데이터가 있는지 확인하고 인덱스 T에서 데이터를 읽은 다음 T를 업데이트합니다. 기본적으로 두 작업에서 액세스하는 링 버퍼입니다. 작업 순서 (삽입, 업데이트 H, 제거, 업데이트 T)는 데이터 손상이 발생하지 않도록합니다.

여러 생산자 및 단일 소비자 또는 단일 생산자 및 여러 소비자가있는 상황이있는 경우에는 사실상 리소스 제한이 있으며 성능 제한 기가 잠금 메커니즘이있는 OS 오버 헤드보다 유일한 생산자 / 소비자입니다.

그러나 생산자와 소비자가 여러 명이라면 디자인 공간에서 시간을 투자하여보다 체계적인 의사 소통 메커니즘을 얻을 수 없는지 확인할 가치가 있습니다. 이와 같은 경우 단일 큐를 통해 모든 것을 직렬화하면 큐의 효율성이 성능의 중심 결정 요인이됩니다.


1
나는 이것을 +1하려고했지만, 틀렸다 : 잠금없는 큐는 여러 독자와 작가를 위해 구현할 수 있으며, 더 복잡합니다. (Lock-Free Queues google.com/search?q=michael%20scott%20queue 에서 Michael + Scott의 논문을보십시오. )
Jason S

1
@Jason S-Scott 용지는 잠금없는 삽입 및 제거 작업에 대한 재진입을 구체적으로 주장합니까? 그렇다면 추출하여 게시 할 수 있다면 많은 사람들에게 귀중한 자산이 될 것입니다. 독자는 인용 된 논문이 특수한 기계 지침을 사용하지만 위의 게시물에서 나의 입장은 그러한 지침을 가정하지 않았다는 점에 유의해야합니다.
JustJeff

1
잠금없는 알고리즘의 비용은 일반적으로 CAS 또는 이와 동등한 지침에 의존합니다. 그러나 재진입은 어떻게 이루어 집니까? 뮤텍스 + 잠금 구조에는 적합하지만 데이터 구조 작업에는 적합하지 않습니다.
Jason S

2

큐 자체에로드 스토어 독점, 비교 교환 또는 유사한 기본 요소와 작업하기에 충분히 작은 항목이 큐에 있으면 잠금없는 다중 생산자 단일 소비자 큐에서 효율적인 조작을 얻을 수 있습니다. 빈 대기열 슬롯에 예약 된 값 또는 예약 된 값. 대기열에 쓸 때 기록기는 비교 교환을 수행하여 데이터를 다음 빈 슬롯에 저장하려고 시도합니다. 실패하면 기록기는 다음 슬롯을 시도합니다. 대기열이 다음 빈 슬롯에 대한 포인터를 유지하지만 포인터 값은 "권고"입니다. 시스템이로드 스토어 독점이 아닌 비교 교환을 사용하는 경우, 다른 '빈 슬롯'값의 '패밀리'가 필요할 수 있습니다. 그렇지 않으면, 작성기가 빈 큐 슬롯을 찾아서 쓰기를 시도하면, 다른 작가는 슬롯을 쓰고 독자는 그것을 읽습니다. 첫 번째 작가는 자신도 모르는 곳에 자신의 데이터를 넣을 수 있습니다. 상점 독점은 데이터가 이전 값으로 다시 쓰여지더라도 기록되었음을 감지하므로로드 저장소 독점을 사용하는 시스템에서는이 문제점이 발생하지 않습니다.


1

대기열 위에 쓰면보다 효율적으로 대기열에 액세스 할 수 있습니다. 일반적으로 대부분의 RTOS는 뮤텍스를 획득 할 필요가없는 대기열 앞에 추가 할 수 있도록 지원합니다. 그러나 데이터를 더 빠르게 실행하려는 경우 가능한 한 대기열 앞에 추가를 사용하십시오. 일반적으로 대기열 구조에는 최대 크기 제한이 있으므로 모든 데이터를 대기열에 넣지 않을 수 있으므로 포인터를 전달하는 것이 항상 쉽습니다.

건배!!


1

큐는 본질적으로 느리지 않습니다. 그것들 의 구현 이 될 수 있습니다.

맹목적으로 데이터를 복사하고 동기 대기열을 사용하는 경우 성능이 저하됩니다.

다른 포스터에서 알 수 있듯이 잠금이없는 대안이 있습니다. 단일 생산자 / 단일 소비자 사례는 간단합니다. 여러 생산자 및 소비자의 경우 Michael과 Scott잠금없는 큐 알고리즘 (이름은 성)이 표준이며 Java의 ConcurrentLinkedQueue 의 기본으로 사용됩니다 .

경우에 따라 대기열의 필요성을 최적화 할 수는 있지만 일반적으로 작업을 분리하여 시스템에 큰 단순화 이점을 제공하는 동시성 보장을 제공합니다.


마이클 앤 스콧 (Michael & Scott) 논문에서 : "이것은 보편적 인 원자 기본 요소를 제공하는 기계에 대한 명확한 선택 알고리즘이다 (예를 들어, 비교 / 스왑 또는 링크 / 저장 조건부로드)." 이것이 실제로 스레드를 정확히 잠그지 는 않을 수도 있지만 여기에는 동기화 형식이 있습니다.
JustJeff

당신은 요점이 있습니다. 메모리 장벽에 대한 독점 액세스에서 동시성 요구 사항을 줄일 수 있습니다.
Jason S
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.