문제

~이다 Interlocked.Increment(ref x) 더 빠르거나 느리게 x++ 다양한 플랫폼에서 INT와 오랜 시간이 있습니까?

도움이 되었습니까?

해결책

동작이 원자 적으로 발생하도록 강요하고 메모리 장벽 역할을하여 프로세서의 메모리 액세스를 명령어 주위에 다시 주문하는 능력을 제거하기 때문에 느립니다.

interlocked.increment 스레드간에 공유 할 수있는 상태에서 작업이 원자가되기를 원할 때 x ++를 완전히 대체 할 수있는 것은 아닙니다.

다른 팁

우리의 경험에서 Windows의 InterlockedIncrement () 등은 상당히 큰 영향을 미칩니다. 하나의 샘플 케이스에서는 인터록을 제거하고 ++/를 대신 사용 할 수있었습니다. 이 단독만이 런 타임을 140 초에서 110 초로 줄였습니다. 내 분석은 인터록이 메모리 라운드 트립을 강요한다는 것입니다 (그렇지 않으면 다른 코어가 어떻게 볼 수 있습니까?). L1 캐시 읽기/쓰기는 약 10 클럭 사이클이지만 메모리는 100과 같이 읽기/쓰기입니다.

이 샘플 사례에서는 약 10 억으로 증가/감소 작업 수를 추정했습니다. 따라서 2GHz CPU에서 이것은 ++/-의 경우 5 초, 인터록의 경우 50 초입니다. 여러 스레드에 대한 차이와 30 초에 가깝습니다.

잠시 생각하면 Increment 호출은 증분 연산자의 간단한 응용 프로그램보다 더 빠를 수는 없습니다. 그렇다면 컴파일러의 증분 연산자 구현이 호출됩니다. Increment 내부적으로, 그들은 동일하게 수행 할 것입니다.

그러나 직접 테스트함으로써 볼 수 있듯이, 그들은 동일하게 수행하지 않습니다.

두 옵션은 다른 목적을 가지고 있습니다. 증분 연산자를 일반적으로 사용하십시오. 사용 Increment 작업이 원자력이 필요하고 해당 변수의 다른 모든 사용자도 인터 로크 작업을 사용하고 있다고 확신합니다. (그들이 모두 협력하지 않으면 실제로 도움이되지 않습니다.)

느린다. 그러나 스칼라 변수에서 스레드 안전성을 달성하기 위해 내가 아는 가장 성능있는 일반적인 방법입니다.

레지스터를 업데이트하는 CPU 버스 잠금 장치 대를 수행해야하기 때문에 항상 느려집니다. 그러나 최신 CPU는 거의 등록 성능을 달성하므로 실시간 처리에서도 무시할 수 있습니다.

내 성능 테스트 :

휘발성 : 65,174,400

잠금 : 62,428,600

연동 : 113,248,900

TimeSpan span = TimeSpan.FromSeconds(5);

object syncRoot = new object();
long test = long.MinValue;

Do(span, "volatile", () => {

    long r = Thread.VolatileRead(ref test);

    r++;

    Thread.VolatileWrite(ref test, r);
});

Do(span, "lock", () =>
{
    lock (syncRoot)
    {
        test++;
    }
});

Do(span, "interlocked", () =>
{
    Interlocked.Increment(ref test);
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top