C ++보다 C ++이 얼마나 빠릅니까?


246

아니면 지금 다른 방향입니까?

내가 들었던 것에서 C #이 C ++보다 빠르다는 영역이 있지만 직접 테스트 할 용기는 없었습니다.

이러한 차이점을 자세히 설명하거나 이에 대한 정보를 얻을 수있는 적절한 장소를 알려줄 수 있다고 생각했습니다.


7
더 이상 임의의 벤치 마크가 게시되지 않도록 보호합니다. 사건을 제기 할 수 있다고 생각되면 10 명의 담당자가 필요합니다.
Robert Harvey

2
어쨌든 이것은 의견 / 주장으로 어떻게 닫히지 않습니까? 여전히 StackOverflow에 있지 않습니까? (닫기를 제안하지 않고 단지 호기심을 갖습니다. 나는 의견이 많은 논쟁
Bill K

1
: 우리가 IL가 CPP로 변환 할 수있는 시대에 살고 있음을 주어 거기에서 최적화 거의 논쟁의 질문입니다 docs.unity3d.com/Manual/IL2CPP.html
pixelpax

범위를 벗어난 배열 액세스를 확인하는 언어는 그렇지 않은 언어보다 성능이 우수하지 않습니다.
Seva Alekseyev

@SevaAlekseyev이 언어는 컴파일러가 아니라 언어입니다. C ++가 빠르다는 이유 중 하나는 (명백한 것들과는 달리) C ++ 컴파일러가 지난 35 년간 (더 이상은 아님) 주변에 있었기 때문입니다. C # 컴파일러가 시간이 지남에 따라 더 나아지는 것을 막는 것은 없습니다. 언급 한 경우 stackoverflow.com/questions/16713076/…
Trap

답변:


343

JIT가있는 C # 또는 Java와 같은 바이트 코드 기반 언어가 C ++ 코드만큼 빠를 수없는 확실한 이유는 없습니다. 그러나 C ++ 코드는 오랫동안 훨씬 더 빨랐으며 오늘날에도 여전히 많은 경우가 있습니다. 이는 주로 고급 JIT 최적화가 구현하기가 복잡하기 때문이며 실제로 멋진 기능은 지금 막 도착했습니다.

따라서 많은 경우 C ++이 더 빠릅니다. 그러나 이것은 답의 일부일뿐입니다. C ++이 실제로 더 빠른 경우는 고도로 최적화 된 프로그램이며, 전문 프로그래머는 코드에서 지옥을 철저히 최적화합니다. 이 작업은 시간이 많이 걸리고 비용이 많이들뿐만 아니라 지나치게 최적화되어 오류가 발생하기도합니다.

반면, 해석 된 언어의 코드는 아무 것도하지 않고도 이후 버전의 런타임 (.NET CLR 또는 Java VM)에서 더 빨라집니다. 그리고 JIT 컴파일러가 포인터를 사용하는 언어에서는 불가능한 유용한 최적화가 많이 있습니다. 또한 일부는 가비지 수집이 일반적으로 수동 메모리 관리만큼 빠르거나 빠르지 않아야한다고 주장합니다. 일반적으로 C ++ 또는 C에서이 모든 것을 구현하고 달성 할 수 있지만 훨씬 더 복잡하고 오류가 발생하기 쉽습니다.

도널드 크 누스 (Donald Knuth)는“조기 최적화는 모든 악의 근원”이라고 말했다. 응용 프로그램이 주로 성능이 매우 중요한 산술로 구성되고 병목 현상이 발생하고 C ++에서는 더 빨라질 것이라는 것을 확실히 알고 있다면 C ++이 다른 응용 프로그램과 충돌하지 않을 것입니다. 요구 사항은 C ++로 이동하십시오. 다른 경우에는 먼저 가장 적합한 언어로 응용 프로그램을 올바르게 구현하는 데 집중 한 다음 너무 느리게 실행되면 성능 병목 현상을 찾은 다음 코드를 최적화하는 방법에 대해 생각하십시오. 최악의 경우 외부 함수 인터페이스를 통해 C 코드를 호출해야 할 수 있으므로 하위 언어로 중요한 부분을 작성할 수 있습니다.

올바른 프로그램을 최적화하는 것은 상대적으로 쉽지만 최적화 된 프로그램을 수정하는 것이 훨씬 어렵다는 점에 유의하십시오.

속도 이점의 실제 비율을 제공하는 것은 불가능하며 코드에 따라 크게 다릅니다. 대부분의 경우 프로그래밍 언어 구현은 병목 현상이 아닙니다. http : //benchmarksgame.alioth.debian .


92
<quote> 이후 버전의 런타임에서 해석 언어의 코드가 빨라짐 </ quote> 더 나은 버전의 컴파일러에서 컴파일 한 코드도 빨라집니다.
Martin York

47
실제로 최소한 하나의 이유가 있습니다. JIT는 빨라야하며 C ++ 컴파일러가 사용할 수있는 다양한 고급 최적화에 시간을 소비 할 수 없습니다.
Nemanja Trifunovic

63
"하지만 일반적으로 과도한 최적화로 인해 오류가 발생합니다." [필수 인용이 필요하다]. 나는 국립 연구소에서 일하고 코드에서 지옥을 최적화합니다. 일반적으로 버그가있는 코드는 아닙니다.
토드 감 블린

35
"올바른 프로그램을 최적화하는 것은 상대적으로 쉽지만 최적화 된 프로그램을 수정하는 것은 훨씬 어렵다"
gradbot

20
Inge : 올바른 길을 가고 있는지 확실하지 않습니다. 예, C #은 다른 언어로 구현되었지만 JIT 컴파일러는 기계어 코드를 생성하므로 해석되는 언어가 아닙니다. 따라서 C ++ 구현에 의해 제한되지 않습니다. 왜 관리자를 무언가에 추가하는 것이 본질적으로 더 빠르다고 생각하는지 확실하지 않습니다.
Martin Probst

202

C #은 빠르지는 않지만 귀하 / ME를 더 빠르게 만듭니다. 그것이 내가하는 일에 대한 가장 중요한 척도입니다. :)


68
하하,이 주제에 대해 Larry Wall의 좋은 인용문이 있습니다. 그는 펄에 대해 말하고 있지만, 언어와 성능과 관련된 모든 논의에 대해 생각할 수있다. 고가의 컴퓨터 프로그래머를 효율적으로 사용하십시오 "
Falaina

60
1. "C #은 C ++보다 훨씬 빠릅니다."2. "실제 일 수 없습니다"1. "그렇습니다"2. "얼마나 많은가?" 1. "보통 3-4 개월까지"
Dmitry S.

2
실제로 사용하는 라이브러리에 의존하는 C ++의 경우 C #은 일반적으로 더 빠르지 않으며 .NET은 생산성을 말할 때입니다.
Ion Todirel

C 대신 Python을 사용하여 코드를 작성할 수있는 이유도 마찬가지입니다. 그러나 계산을 많이 한 후에 성능의 차이를 느낄 수 있습니다.
Ch3shire

그것은 당신이 익숙한 것에 달려 있습니다. C #에서보다 C ++에서 훨씬 빠르게 프로그래밍합니다. 기본 지식을 위해 바퀴를 재발 명하고 싶지 않기 때문에 라이브러리 지식은 그것의 큰 부분입니다. C / C ++의 주요 문제는 스마트 포인터로 해결되는 포인터 관리였습니다. C ++에는 .NET 및 Java가 제공하는 광범위한 라이브러리가 없으며 개발 속도를 크게 높일 수 있다고 말합니다. 표준 소년들이 라이브러리 확장 대신 템플릿 개선에 시간을 보내기를 원하기 때문에 이것은 곧 해결되지 않을 것입니다.
gast128

87

오렌지 5 개가 더 빠릅니다. 또는 오히려 : (올바른) 담요 답변이 없을 수 있습니다. C ++는 정적으로 컴파일 된 언어입니다 (그러나 프로파일 가이드 최적화도 있습니다). C #은 JIT 컴파일러의 도움을받습니다. “얼마나 더 빠른가”와 같은 질문에 대해 질서를내는 것조차도 대답 할 수없는 많은 차이가 있습니다.


177
당신은 당신의 터무니없는 다섯 오렌지 주장을 뒷받침 할 증거가 있습니까? 내 실험은 템플릿 메타 프로그래밍을 할 때 3 망고 개선으로 최대 2 개의 오렌지를 가리 킵니다.
Alex

42
효모에서 그는 엄청나게 빨리 오르지 않습니다.
Chris

11
내 경험상 그것은 5.2 오렌지입니다. 그러나 이것은 사용하는 과일-오 미터에 따라 다릅니다.
Dio F

4
업데이트, StackOverflow의 자체가 엉망 핸들 (수 있어야하는 것보다 300 개 바나나 악화) 비효율적, 따라서 적은 바나나 논평 : meta.stackexchange.com/questions/254534/...
KeksArmee

87

나는 다음과 같이 진술함으로써이 질문에 대해 받아 들여지고 잘 찬성 된 답변의 일부에 동의하지 않는 것으로 시작할 것입니다.

실제로 JITted 코드가 올바르게 최적화 된 C ++ (또는 런타임 오버 헤드가없는 다른 언어) 프로그램보다 느리게 실행되는 이유는 다음과 같습니다.

  • 런타임에 JITting 코드에 소비 된 계산주기는 정의상 프로그램 실행에 사용할 수 없습니다.

  • JITter의 모든 핫 경로는 CPU의 명령 및 데이터 캐시 코드와 경쟁합니다. 우리는 캐시가 성능면에서 지배적이며 C ++와 같은 모국어에는 정의에 따라 이러한 유형의 경합이 없습니다.

  • 런타임 최적화 프로그램의 시간 예산은 컴파일 타임 최적화 프로그램의 예산 보다 훨씬 더 제한적입니다 (다른 의견자가 지적했듯이)

결론은 : 궁극적으로, 당신은 할 것이다 거의 확실하게 당신이 C #의 수보다 C ++로 빠른 구현을 만들 수 있습니다 .

이제 말했듯이, 작업, 문제 영역, 하드웨어, 구현 품질 및 기타 많은 요인과 같은 변수가 너무 많기 때문에 실제로 얼마나 빨리 정량화 할 수 없습니까? 시나리오에서 테스트를 실행하여 성능의 차이를 판별 한 후 추가 노력과 복잡성에 대한 가치가 있는지 여부를 결정합니다.

이것은 매우 길고 복잡한 주제이지만 C #의 런타임 최적화 프로그램이 우수하다는 완전성을 위해 언급 할 가치가 있으며 런타임에 C ++에서는 컴파일 타임으로 사용할 수없는 특정 동적 최적화를 수행 할 수 있습니다 ( static) 옵티 마이저. 그럼에도 불구하고, 장점은 여전히 ​​기본 응용 프로그램의 법원에 깊이 있지만, 동적 최적화 프로그램은 위에서 언급 한 " 거의 확실하게"한정자 의 이유입니다 .

-

상대적인 성과 측면에서, 나는 다른 답변에서 본 인물과 토론에 혼란을 겪었습니다. 따라서 동시에 차임 할 것이라고 생각했으며 위에서 언급 한 진술에 대한 약간의 지원을 제공했습니다.

이러한 벤치 마크 문제의 큰 부분은 C #을 작성하는 것처럼 C ++ 코드를 작성할 수 없으며 대표 결과를 얻을 수 있다는 것입니다 (예 : C ++에서 수천 개의 메모리 할당을 수행하면 끔찍한 숫자가 나타납니다).

대신 약간 더 관용적 인 C ++ 코드를 작성하고 제공된 @Wiory C # 코드와 비교했습니다. C ++ 코드에서 변경된 두 가지 주요 사항은 다음과 같습니다.

1) 사용 된 vector :: reserve ()

2) 더 나은 캐시 위치를 달성하기 위해 2d 배열을 1d로 평면화했습니다 (연속 블록)

C # (. NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

런타임 (릴리스) : 초기화 : 124ms, 채우기 : 165ms

C ++ 14 (클랑 v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

런타임 (릴리스) : 초기화 : 398µs (예, 마이크로 초), 채우기 : 152ms

총 실행 시간 : C # : 289ms, C ++ 152ms (약 90 % 더 빠름)

관찰

  • C # 구현을 동일한 1d 배열 구현으로 변경하면 Init : 40ms, Fill : 171ms, Total : 211ms가 발생했습니다 ( C ++은 여전히 ​​거의 40 % 빠릅니다 ).

  • C ++에서 "빠른"코드를 디자인하고 작성하는 것이 어느 언어로든 "일반"코드를 작성하는 것보다 훨씬 어렵습니다.

  • C ++에서 성능이 저하되는 것은 놀랍도록 쉽습니다. 우리는 예약되지 않은 벡터 성능으로 그것을 보았습니다. 그리고 이런 함정이 많이 있습니다.

  • C #의 성능은 런타임에 진행되는 모든 것을 고려할 때 다소 놀랍습니다. 그리고 그 성능은 비교적 접근하기 쉽습니다.

  • C ++과 C #의 성능을 비교 한 일화적인 데이터 : https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

결론적으로 C ++은 성능을 훨씬 더 잘 제어 할 수 있다는 것입니다. 포인터를 사용 하시겠습니까? 참조? 스택 메모리? 더미? 동적 다형성 또는 정적 다형성 (템플릿 / CRTP를 통해)으로 vtable의 런타임 오버 헤드를 제거합니까? 당신이 ... 어이 C ++에서 얻을 이상적으로 너무 솔루션 최선 주소 문제가 당신에게있는 거 태클이 (더) 자신이 모든 선택을 할 수 있도록.

위의 사소한 예에서도 성능이 크게 개선되었지만 액세스에 더 많은 투자가 필요하다는 것을 알 수 있기 때문에 실제로 해당 제어를 원하거나 필요로하는지 자문 해보십시오.


16
@Quonux는 의견을 보내 주셔서 감사합니다. 물론 이것은 "실제 프로그램"이 아닙니다. 벤치 마크의 요점은이 페이지의 다른 곳에서 제공되는 C # 벤치 마크를 리팩터링하여 JITted 코드가 네이티브 코드보다 빠르다는 증거입니다.
U007D

9
@Quonux 왜 그렇게 써야합니까? 내가 당신을 좋아하는 사람들입니다.
Markus Knappen Johansson

5
@MarkusKnappenJohansson 나는 나쁜 하루를 보냈다;), 나는 단지 인간이고, 나의 공감대를 제거했지만 내 의견은 여전히 ​​적용됩니다. 오, "멍청한"사람들이 있기 때문에 그렇게 싫어하지 마십시오 :). 좋은 것을 가져라.
Quonux

9
완전히 실패한 벤치 마크. C ++ 버전에서는 단순히 메모리의 일부를 예약 한 다음 해당 작업을 실행하는 데 마이크로 초가 걸리는 방법에 감탄합니다. C # 버전에서는 5000 개의 ARRAYS (메모리에 객체를 인스턴스화)를 작성합니다. C ++은 C #보다 빠르지 만 차이점은 40 %에 가깝지 않습니다. 현재는 10 % 미만입니다. 귀하의 예가 보여주는 것은 프로그래머가 선택한 언어를 고수해야한다는 것입니다 (그리고 프로필에서 경력 C ++ 프로그래머라는 것이 분명합니다). C #에서는 2D 배열을 수행 할 수 있습니다 int[,]...
nikib3ro

3
내가 알 수 있듯이 C ++ 예제의 코드는 말 그대로 미리 메모리를 할당하는 것입니다. 적절한 C # 구현은 단순히 2 차원 배열을 1 차원 형식으로 인덱싱하는 데 필요한 메모리를 할당하는 'List <double> arrs = new List <double> (ROWS * COLS)'를 작성합니다 (예 : C ++에서 수행 한 작업). 2 차원 배열을 할당하고 수동으로 평탄화 할 이유가 전혀 없습니다. 사전 테스트에서 방대한 양의 반복이 떨리는 성능의 원인입니다. 오버 헤드가 여전히 C #에서는 더 많지만 상당한 금액은 아니라고 생각합니다.
JDSweetBeat 1

62

내 경험 (그리고 두 언어로 많은 일을했습니다)에서 C ++과 비교 한 C #의 주요 문제는 높은 메모리 소비이며 제어 할 수있는 좋은 방법을 찾지 못했습니다. .NET 소프트웨어의 속도를 늦추는 것은 메모리 소비였습니다.

또 다른 요소는 JIT 컴파일러가 런타임에 실행되기 때문에 고급 최적화를 수행하는 데 너무 많은 시간을 할애 할 수 없으며 최종 사용자가 시간이 너무 오래 걸리면이를 알 수 있다는 것입니다. 반면에 C ++ 컴파일러는 컴파일 타임에 최적화를 수행하는 데 필요한 모든 시간을 갖습니다. 이 요소는 메모리 소비보다 훨씬 덜 중요합니다 (IMHO).


6
작업중인 한 프로젝트에서 많은 GB를 동시에 메모리에 보유하고 모든 데이터에 대해 비싼 계산을 수행하는 등 엄청난 양의 데이터를 채굴해야했습니다. 이는 모든 할당을 정확하게 제어해야했기 때문에 C ++이 유일한 선택이었습니다. C ++의 경우 +1 반면에, 그것은 단지 하나의 프로젝트였습니다. 우리는 대부분의 시간을 느린 시뮬레이터와 상호 작용하는 시스템을 작성하는 데 보냈고 디버깅은 악몽이 될 수 있으므로 프로그래머 시간 최적화 언어를 다른 모든 것에 사용할 수 있기를 바랍니다. 물건.
Bogatyr

7
@ IngeHenriksen : Dispose 패턴을 잘 알고 있지만 관리되는 메모리에는 전혀 도움이되지 않습니다.
Nemanja Trifunovic

10
@IngeHenriksen을 배치하면 Dispose 메소드가 호출 된 것만 보장됩니다. 처리는 가비지 수집 메모리를 해제하지 않습니다. Dispose 메서드는 파일 핸들과 같은 관리되지 않는 리소스를 정리하기위한 것이며 메모리 관리와는 아무런 관련이 없습니다.
doug65536

1
@NemanjaTrifunovic : "JIT 컴파일러는 고급 최적화를 수행하는 데 너무 많은 시간을 할애 할 수 없습니다." JIT가 수행하지 않는 최적화가 너무 오래 걸리기 때문에 인용 할 수 있습니까?
Jon Harrop

5
@ user3800527 : RAM을 추가하는 것이 항상 가능하더라도 (그리고 MS가 각 MS Office 사용자에게 RAM을 추가한다고 상상해보십시오) 문제를 해결할 수는 없습니다. 메모리는 계층 적이며 C # 프로그램은 C ++보다 많은 캐시 미스를 갖습니다.
Nemanja Trifunovic

35

C ++이 여전히 우위에 있고 (수년 동안) 앞으로 다가올 결정이 컴파일 타임에 사전 결정될 수있을 때 발생하는 특정 시나리오입니다.

일반적으로 캡슐화 및 지연된 의사 결정은 코드를보다 역동적이고 변화하는 요구 사항에 쉽게 적용하고 프레임 워크로 사용하기 쉽기 때문에 좋습니다. 이것이 C #의 객체 지향 프로그래밍이 매우 생산적이고 "일반화"라는 용어로 일반화 될 수있는 이유입니다. 불행하게도, 이러한 특정 종류의 일반화는 런타임에 비용이 발생합니다.

일반적으로이 비용은 실질적이지 않지만 가상 메소드 호출 및 오브젝트 작성의 오버 헤드로 인해 차이가 발생할 수있는 애플리케이션이 있습니다 (특히 가상 메소드가 메소드 호출 인라이닝과 같은 다른 최적화를 방해하므로). 당신이없는 일반화 다른 종류의 달성하기 위해 템플릿을 사용할 수 있기 때문에 C ++는 큰 장점을 가지고있는 곳이다 런타임에 영향을하지만 반드시 덜 다형성 OOP 이상입니다. 실제로 OOP를 구성하는 모든 메커니즘은 템플릿 기술과 컴파일 타임 해상도 만 사용하여 모델링 할 수 있습니다.

이러한 경우 (그리고 종종 특수한 문제 영역으로 제한됨), C ++는 C # 및 유사한 언어에 대해 승리합니다.


6
실제로 Java VM (및 .NET)은 동적 디스패치를 ​​피하기 위해 많은 시간을 투자합니다. 기본적으로 다형성을 피할 수있는 방법이 있다면 VM이 그렇게 할 것입니다.
Martin Probst

3
+1 나는 항상 C ++을 아는 C # 동료들에게 이것이 의미를 인식 할 수있는 방법으로 설명하는 데 어려움을 겪고있다. 당신은 오히려 그것을 잘 설명했습니다.
Roman Starkov

9
@crtracy : 고성능 컴퓨팅 응용 프로그램없이 베팅하고 있습니다. 일기 예보, 생물 정보학 및 수치 시뮬레이션을 고려하십시오. 다른 코드는 동일한 수준의 높은 추상화 수준에서 비슷한 성능을 달성 할 수 없기 때문에 이러한 영역에서 C ++의 성능 리드는 줄어들지 않습니다 .
Konrad Rudolph

5
@Jon 사과와 오렌지. 귀하의 구체적인 주장은“메타 프로그래밍의 맥락에서 C #은 C ++보다 수십 배 빠릅니다”이며“사전 컴파일 된 코드를 사용하는 것이 해석 된 코드보다 수십 배 빠릅니다”라는 것이 아닙니다. 우리가 여기에있는 동안, 런타임 코드 생성이 컴파일 타임 코드 생성보다 "일반적"이라고 주장하는 것 역시 명백히 잘못되었습니다. 둘 다 장단점이 있습니다. 컴파일 타임 코드 생성은 유형 시스템을 사용하여 정적 유형 안전을 제공합니다. 런타임 코드 생성은 그렇게 할 수 없습니다 ( 강력한 유형 안전 제공 할 있지만 정적 유형 안전 제공 할 없음 ).
Konrad Rudolph

5
@ user3800527이 답변의 요점을 놓친 것 같습니다. 물론 캡슐화를 해제하고 저수준 구조로 드롭 다운하여이 문제를 해결할 수 있습니다. 대부분의 언어로 어셈블리를 작성할 수 있습니다. C ++ (거의)을 독특하고 고성능 프로그래밍에 적합하게 만드는 것은 런타임 비용 없이 제공되는 높은 수준의 추상화를 만들 수 있다는 것 입니다. 따라서 우수한 성능을 얻기 위해 C ++로 어셈블리와 유사한 코드를 작성할 필요가 없습니다. 잘 작성된 것이 C ++의 손으로 쓴 루프만큼 효율적입니다. C #에는 절대 포함되지 않습니다. sort(arr, generic_comparer)
Konrad Rudolph

20

C ++ (또는 그 문제에 대한 C)를 사용하면 데이터 구조를 세밀하게 제어 할 수 있습니다. 비트 트위스 티를 원하면 해당 옵션이 있습니다. Java / .NET 라이브러리의 내부 데이터 구조를 사용하는 대규모 관리 Java 또는 .NET 앱 (OWB, Visual Studio 2005 )은 수하물을 가지고 다닙니다. 큐브 또는 ETL 디자인을 위해 400MB가 넘는 RAM과 BIDS를 사용하는 OWB 디자이너 세션도 100MB에 도달하는 것을 보았습니다 .

예측 가능한 워크로드 (예 : 프로세스를 여러 번 반복하는 대부분의 벤치 마크와 같은)에서 JIT는 실질적인 차이가 없을 정도로 충분히 최적화 된 코드를 얻을 수 있습니다.

큰 응용 프로그램의 IMO는 코드 자체가 사용하는 데이터 구조만큼 큰 차이가 아닙니다. 응용 프로그램의 메모리가 많은 경우 캐시 사용 효율이 떨어집니다. 최신 CPU의 캐시 미스는 상당히 비쌉니다. C 또는 C ++가 실제로이기는 곳은 CPU 캐시와 잘 작동하도록 데이터 구조 사용을 최적화 할 수있는 곳입니다.


19

그래픽의 경우 표준 C # 그래픽 클래스는 C / C ++를 통해 액세스 한 GDI보다 느립니다. 나는 이것이 언어 자체와는 아무런 관련이 없다는 것을 알고 있습니다. 전체 .NET 플랫폼과 관련이 있지만 그래픽은 개발자에게 GDI 대체품으로 제공되는 것이며 성능이 너무 나빠 그래픽을 감히하지 않을 것입니다. 그것으로.

그래픽 라이브러리의 속도를 확인하는 데 사용하는 간단한 벤치 마크가 있으며 이는 단순히 창에 임의의 선을 그리는 것입니다. C ++ / GDI는 여전히 10000 개의 라인을 가지고 있지만 C # / Graphics는 1000 개의 실시간 작업을 수행하는 데 어려움이 있습니다.


5
나는 당신의 대답에 흥미를 느꼈습니다. 안전하지 않은 코드와 잠금 비트로 동일한 벤치 마크를 테스트하고 임의의 선을 직접 그렸습니까? 이제 그것은 흥미로운 것입니다.
Pedery

2
@Pedery nope 내가하지 않았습니다. 가장 기본적인 방법으로 GDI 및 .NET.Graphics를 사용하십시오. "임의의 선을 직접 그린다"는 것은 무슨 뜻입니까?
QBziZ

1
그렇다면 C #의 속도에 대한보다 현실적인 메트릭스를 얻기 위해 이것을 테스트하는 것이 좋습니다. 이 기술에 대한 좋은 개요는 다음과 같습니다. bobpowell.net/lockingbits.htm
Pedery

6
그것은 우리가하고 싶은 것이 아니며, 프레임 버퍼에 별도의 픽셀을 넣습니다. 모든 것을 직접 구현해야하는 경우 코딩 할 API / 플랫폼의 요점은 무엇입니까? 나에게 이것은 논증이 아니다. 우리는 선을 그리기 위해 GDI의 프레임 버퍼에 별도의 픽셀을 넣을 필요가 없었으며 .NET에서도 그렇게 할 계획이 없습니다. 필자의 견해로는 현실적인 메트릭을 사용했으며 .NET이 느리다는 것이 밝혀졌습니다.
QBziZ

1
글쎄, 나는 얼룩 탐지가 무엇인지 약간의 아이디어를 가지고 있지만, 한 번의 타이밍을 말하는 것은 전혀 아무것도 증명하지 못한다. C ++로 작성 했습니까? JavaScript로? 그리고 그것들을 C #의 것과 비교 했습니까? 게다가 블롭 감지가 많은 그래픽 프리미티브를 사용하고 있다고 생각하지 않습니다. 틀린 경우 수정하십시오.하지만 픽셀에서 작업을 수행하는 통계 알고리즘이라고 생각합니다.
QBziZ

13

가비지 수집은 Java #을 실시간 시스템에 사용할 수없는 주된 이유입니다.

  1. GC는 언제 발생합니까?

  2. 얼마나 걸릴까요?

이것은 비 결정적입니다.


5
나는 거대한 Java 팬은 아니지만 Java가 실시간 친화적 인 GC를 사용할 수 없다고 말하는 것은 없습니다.
Zan Lynx

5
보고 싶다면 실시간 GC 구현이 많이 있습니다. (GC는 연구 논문으로 넘쳐나 는 영역입니다 )
Arafangion

FWIW의 Richard Jones는 최신 실시간 GC 디자인을 다루는 업데이트 된 버전의 가비지 콜렉션을 발표했습니다.
Jon Harrop

11
이것은 말도 안되는 논쟁이며 Windows (및 Linux)는 실시간 OS가 아닙니다. C ++ 코드는 언제든지 여러 18ms 슬롯으로 교체 할 수 있습니다.
Henk Holterman

2
@HenkHolterman True이지만, 항상 부트 로더를 어셈블리로 작성하고이를 애플리케이션의 커널 부트 스트랩에 묶고 하드웨어에 대해 직접 RT ++에서 C ++ 앱을 실행할 수 있습니다. C #에서는이 작업을 수행 할 수 없으며 C #에서 사전 컴파일 된 어셈블리 만 모방하고 많은 C 코드를 사용하여 C #을 사용하는 것이 의미가 없습니다. C #은 .NET 프레임 워크 없이는 쓸모가 없기 때문에이 모든 것을 읽는 것은 다소 재미 있습니다.
zackery.fix 2018 년

11

우리는 C #이 성능면에서 C ++과 비교할 수 있는지 확인해야했고이를 위해 몇 가지 테스트 프로그램을 작성했습니다 (두 언어 모두 Visual Studio 2005 사용). 가비지 수집이없고 언어 (프레임 워크 아님) 만 고려하면 C #은 기본적으로 C ++과 동일한 성능을 갖습니다. 메모리 할당이 C ++보다 C ++에서 훨씬 빠르며 데이터 크기가 캐시 라인 경계를 넘어서 증가 할 때 C #은 결정론에서 약간 우위에 있습니다. 그러나이 모든 비용은 결국 지불해야했으며 가비지 수집으로 인해 C #의 비 결정적 성능 적중 형태로 막대한 비용이 발생했습니다.


1
C ++에서는 다른 할당 방법을 사용할 수있는 옵션이 있으므로 C #에서 메모리가 할당 된 방법 (AOT?)에 따라 C ++에서 동일한 방식으로 (그러나 훨씬 빠릅니다) 수행 될 수 있습니다.
zackery.fix 2018 년

5
@ zackery.fix .NET은 새로운 객체를 할당하기 위해 포인터를 이동하기 만하면되기 때문에 힙 할당에서 흥미로운 우위를 가지고 있습니다. 이것은 압축 가비지 수집기 때문에 가능합니다. 물론 C ++에서도 같은 작업을 수행 할 수 있지만 C ++은 그렇지 않습니다. 같은 주장을 사용하여 "C #은 할 수는 있지만 그렇게 할 수는 없다"고 "C ++은 할 수 없지만 그렇게 할 수는있다"고 말하는 것이 재미있다. :)
Luaan

9

평소와 같이 응용 프로그램에 따라 다릅니다. C #이 무시할 수있을 정도로 느리거나 C ++이 5 배나 10 배 더 빠른 경우가 있습니다 (특히 작업을 쉽게 SIMD 할 수있는 경우).


정적으로 컴파일 된 바닐라 C ++ 프로그램에는 JIT 컴파일러가 내장되어 있지 않기 때문에 해석 만 사용할 수 있기 때문에 VM에 대한 최상의 사례는 생성 된 코드의 런타임 컴파일 (예 : 런타임에 읽은 정규식과 일치)입니다.
Jon Harrop

향후 참고 사항 : .NET은 2014 년부터 SIMD 및 친구를 지원하지만 널리 사용되지는 않습니다.
Luaan

9

나는 그것이 당신이 요구하는 것이 아니라는 것을 알고 있지만, C #은 종종 C ++보다 작성하는 것이 빠르며 , 이는 상업적 환경에서 큰 보너스입니다.


2
나는 그것이 대부분의 시간이 더 빠르다고 말하고 싶다 :)
Trap

8

C / C ++는 큰 배열이나 배열에 대한 반복 / 반복 (모든 크기)이있는 프로그램에서 훨씬 더 잘 수행 할 수 있습니다. 무거운 배열 연산은 거의 모든 그래픽 연산의 기본이기 때문에 C / C ++에서 그래픽이 일반적으로 훨씬 빠르기 때문입니다. .NET은 모든 안전 검사로 인해 배열 인덱싱 작업에서 느리게 알려져 있으며 특히 다차원 배열의 경우에 해당합니다 (예 : 직사각형 C # 배열이 들쭉날쭉 한 C # 배열보다 느림).

C / C ++의 보너스는 포인터를 직접 고수하고 Boost std::vector및 기타 고급 컨테이너와 inline가능한 모든 작은 기능을 피하면 가장 두드러집니다 . 가능하면 구식 배열을 사용하십시오. 예, 고급 컨테이너를 피할 때 Java 또는 C #에서 수행 한 것과 동일한 작업을 수행하려면 더 많은 코드 줄이 필요합니다. 동적 크기의 배열이 필요한 경우 new T[]해당 delete[]명령문 과 짝을 이루 거나 사용해야합니다.std::unique_ptr) — 추가 속도의 가격은 더 신중하게 코딩해야한다는 것입니다. 그러나 그 대가로 관리되는 메모리 / 가비지 수집기의 오버 헤드를 제거하여 Java 및 .NET의 대규모 객체 지향 프로그램과 대규모 관리 대상 프로그램의 실행 시간을 20 % 이상 쉽게 얻을 수 있습니다. 메모리 어레이 인덱싱 비용. C ++ 앱은 특정 경우에 멋진 컴파일러 스위치를 활용할 수도 있습니다.

저는 C, C ++, Java 및 C #의 전문 프로그래머입니다. 최근에 후자의 3 개 언어로 똑같은 알고리즘 프로그램을 구현하는 경우는 드물었습니다. 이 프로그램에는 많은 수학 및 다차원 배열 작업이있었습니다. 나는 이것을 3 개 언어 모두에서 크게 최적화했다. 결과는 내가 덜 엄격한 비교에서 일반적으로 보는 것의 전형적인 결과입니다. Java는 C #보다 약 1.3 배 빠르며 (대부분의 JVM은 CLR보다 최적화되어 있으며) C ++ 원시 포인터 버전은 C #보다 약 2.1 배 빠릅니다. C # 프로그램은 안전한 코드 만 사용했습니다 unsafe. 키워드 를 사용하기 전에 C ++로 코드를 작성할 수도 있습니다 .

누군가 내가 C #에 대해 뭔가가 있다고 생각하지 않도록 C #이 아마도 내가 가장 좋아하는 언어라고 말하면서 닫을 것이다. 내가 지금까지 본 가장 논리적이고 직관적이며 빠른 개발 언어입니다. C #에서 프로토 타이핑을 모두합니다. C # 언어는 Java에 비해 작고 미묘한 장점이 많습니다 (예, Microsoft가 게임에 늦게 들어 와서 Java를 복사함으로써 Java의 많은 단점을 해결할 수있는 기회가 있음을 알고 있습니다). 자바 Calendar클래스 누구에게 건배 ? Microsoft가 CLR 및 .NET JITter를 최적화하기 위해 실제 노력을 기울이면 C #이 심각하게 인수 할 수 있습니다. 솔직히 그들이 아직 C # 언어로 많은 일을 해냈다는 것에 놀랐습니다. 왜 컴파일러 최적화를 사용하지 않습니까? 어쩌면 우리 모두가 애원한다면


3
"당신은 당신의 페어링을 기억해야합니다 new T[]A가 대응 delete[]" - 아니 당신은하지 않습니다. 거기에 std::unique_ptr당신을 위해 그렇게 할 수 있습니다.
emlai

왜 그래픽으로 무언가를 썼다고 가정하면 왜 안전 코드를 C #으로 작성하고 안전하지 않은 코드를 사용하고 다시 비교해 보셨습니까?
user3800527

7

> 내가들은 내용에서 ...

귀하의 어려움은 귀하가들은 내용이 믿을만한 지 판단하는 데있는 것 같으며,이 사이트의 답변을 평가하려고 할 때 어려움이 반복 될 것입니다.

사람들이 여기서 말하는 것이 원래 들었던 것보다 다소 신뢰할 만한지를 어떻게 결정할 것입니까?

한 가지 방법은 증거 를 요구하는 입니다.

사람의 주장이 "C # 빠른 C보다 증명하는 몇 가지 영역이 있습니다 ++"때 그들에게 그들이 그런 말 당신에게 측정을 보여주기 위해 그들에게 당신에게 프로그램을 표시하도록 요청합니다. 때때로 그들은 단순히 실수했을 것입니다. 때때로 당신은 그들이 사실로 보여줄 수있는 것을 공유하기보다는 단지 의견을 표현하고 있다는 것을 알게 될 것입니다.

사람들이 주장하는 내용에 정보와 의견이 혼동되는 경우가 많으며, 어느 것이 어떤 것인지 시도하고 정리해야합니다. 예를 들어,이 포럼의 답글에서 :

  • " 이 코드는 대부분 코드와 거의 유사하지 않기 때문에 http://shootout.alioth.debian.org/ 에서 많은 회의론을 가지고 벤치 마크를 수행 하십시오 ."

    "이 큰 테스트 산술 코드"의 의미 를 실제로 이해했는지 확인한 다음 저자가 실제로 자신의 주장이 사실임을 보여 주 었는지 스스로에게 물어보십시오.

  • "그것은 개별 프로그램이 얼마나 잘 최적화되었는지에 달려 있기 때문에 다소 쓸모없는 테스트입니다. 나는 그 중 일부를 4-6 배 이상 가속화하여 최적화되지 않은 프로그램 간의 비교가 바보."

    저자가 실제로 "그들 중 일부를 4-6 배 이상 가속시킬 수 있음"을 보여 주 었는지 스스로에게 물어보십시오. 쉽게 주장 할 수 있습니다!


나는 당신에게 더 이상 동의 할 수 없었고 그것이 바로이 포럼에서 질문 한 이유입니다 ... 결국, 대답은 어딘가에 있어야합니까? :)
Trap

1
예. 대답은 "그것은 달려있다"입니다.
user49117

6

C ++에서 Intel TBB 및 OpenMP를 사용할 때 '거의 병렬 처리'문제의 경우 C # 및 TPL로 수행 한 유사한 (순수한 수학) 문제와 비교하여 대략 10 배의 성능 향상이 관찰되었습니다. SIMD는 C #이 경쟁 할 수없는 영역이지만 TPL에 상당한 오버 헤드가 있다는 인상을 받았습니다.

즉, 멀티 스레드를 수행하고 결과를 빠르게 얻을 수 있다는 것을 알고 성능이 중요한 작업에만 C ++을 사용합니다. 다른 모든 것에는 C # (그리고 때로는 F #)이 좋습니다.


5

실제 결정적인 대답이없는 매우 모호한 질문입니다.

예를 들어; 오히려 C #보다 C ++로 만들어진 3D 게임을하고 싶습니다. 성능은 확실히 훨씬 우수하기 때문입니다. (그리고 나는 XNA 등을 알고 있지만 실제와는 거리가 멀다.)

한편, 앞서 언급 한 바와 같이; 원하는 것을 빨리하고 필요한 경우 최적화 할 수있는 언어로 개발해야합니다.


4
몇 가지 예를 들어 주시겠습니까? C #으로 작성된 게임 느린 게임
Karl

1
설치와 함께 제공되는 예제 응용 프로그램조차 느려졌습니다.
David The Man

9
가비지 수집기는 C #으로 게임을 만드는 데 큰 책임이 있습니다. 명시 적 메모리 관리로 인해 게임 개발이 쉬워졌습니다.
postfuturist

3
대부분의 최신 게임은 GPU로 제한됩니다. 이러한 게임의 경우 (CPU에서 실행되는) 로직이 10 % 느리더라도 문제가되지 않습니다. 여전히 CPU가 아닌 GPU에 의해 제한됩니다. 가비지 콜렉터는 실제 문제이므로 메모리 할당이 제대로 조정되지 않으면 임의의 짧은 정지가 발생합니다.
Michael Entin

2
@postfuturist : PC에서는 그렇지 않습니다. 가비지 컬렉터는 들어오고 나가는 좋은 일을합니다. 그러나, X 박스 360과 준 / 윈도우 7 전화에, 가비지 컬렉터가 아닌 거의 PC에 스마트와 같은; 나는 어느 쪽도 쓰지 않았지만 가비지 수집기를 말 해준 사람들 문제입니다.
BlueRaja-대니 Pflughoeft

5

.NET 언어는 C ++ 코드만큼 빠르거나 더 빠를 수 있지만 C ++ 코드는 일시 정지 가 매우 영리하더라도 .NET 런타임이 GC 에 대해 일시 중지해야하기 때문에 처리량이 더 일정 합니다.

따라서 일시 중지하지 않고 일관되게 빠르게 실행해야하는 코드가있는 경우 .NET은 런타임 GC에 매우주의를 기울이더라도 어느 시점에서 대기 시간 발생 시킵니다.


6
-1 : 이것은 실제로 신화입니다. 첫째, 관용적 C ++의 대기 시간은 실제로 .NET보다 끔찍하고 종종 .NET보다 훨씬 나쁩니다. 왜냐하면 RAII는 큰 데이터 구조가 범위를 벗어나면 소멸자의 눈사태를 유발하는 반면 현대 GC는 점진적이고 .NET은 동시입니다. 둘째, 할당하지 않으면 .NET에서 GC 일시 중지를 실제로 완전히 제거 할 수 있습니다.
Jon Harrop

2
이 작업을 수행하는 경우 대부분의 메소드가 임시 오브젝트를 작성하므로 BCL을 사용하지 않아야합니다.
Florian Doyon

5
이것은 사실입니다. .net 4 이전에는 GC가 증분되었습니다. GC에 대해 한 번에 몇 초 동안 일시 중지되는 대형 C # 앱이 있습니다. 성능이 중요한 앱의 경우 킬러입니다.
저스틴

5
하드웨어를 밀어 붙이는 프로그램이 C ++을 사용하는 이유가 있습니다. 필요할 때 더 세밀하게 조정할 수 있습니다. 시스템을 푸시 할 때만 성능이 중요합니다. 그렇지 않으면 C # 또는 Java를 사용하여 시간을 절약하십시오.
VoronoiPotato

4
캐시 동작을 관리 할 수 ​​없으면 최적화 된 C ++ 코드를 이길 수 없습니다. L1에서 기본 메모리로의 캐시 누락으로 인해 작업이 100 배 느려질 수 있습니다.
DAG

4

이론적으로 장기 실행 서버 유형 응용 프로그램의 경우 JIT 컴파일 언어가 크게 될 수 있습니다. 기본적으로 컴파일 보다 빠를 . JIT 컴파일 언어는 일반적으로 상당히 낮은 수준의 중간 언어로 먼저 컴파일되므로 어쨌든 컴파일 시간에 많은 고급 최적화를 수행 할 수 있습니다. JIT는 응용 프로그램 사용 방법에 대한 데이터가 점점 많아지면서 코드 섹션을 즉시 다시 컴파일 할 수 있다는 장점이 있습니다. 분기 예측이 가능한 한 자주 성공하도록 가장 일반적인 코드 경로를 정렬 할 수 있습니다. 캐시에 둘 다 유지하기 위해 종종 함께 호출되는 별도의 코드 블록을 재정렬 할 수 있습니다. 내부 루프를 최적화하는 데 더 많은 노력을 기울일 수 있습니다.

나는 이것이 .NET 또는 JRE 중 하나에 의해 수행된다는 것을 의심하지만, 대학에있을 때 다시 연구되고 있었기 때문에 이러한 종류의 것들이 어느 시점에서 곧 현실 세계로 나아갈 수 있다고 생각하는 것은 합리적이지 않습니다. .


4

집중적 인 메모리 액세스가 필요한 응용 프로그램. 이미지 조작은 일반적으로 관리되는 환경 (C #)보다 관리되지 않는 환경 (C ++)으로 작성하는 것이 좋습니다. 포인터 산술을 사용하여 최적화 된 내부 루프는 C ++에서 제어하기가 훨씬 쉽습니다. C #에서는 동일한 성능에 근접하기 위해 안전하지 않은 코드에 의존해야 할 수도 있습니다.


4

vectorC ++ 및 C #과 동등한 List2D 배열로 테스트 했습니다 .

Visual C # / C ++ 2010 Express 버전을 사용하고 있습니다. 두 프로젝트 모두 간단한 콘솔 응용 프로그램이며 표준 (사용자 정의 설정 없음) 릴리스 및 디버그 모드에서 테스트했습니다. C # 목록은 내 PC에서 더 빠르게 실행되고 C #에서는 배열 초기화가 더 빠르며 수학 연산이 느려집니다.

Intel Core2Duo P8600@2.4GHz, C #-.NET 4.0을 사용하고 있습니다.

벡터 구현이 C # 목록과 다르다는 것을 알고 있지만 객체를 저장하고 인덱스 접근자를 사용할 수있는 컬렉션을 테스트하고 싶었습니다.

물론 메모리를 비워야합니다 (을 사용할 때마다 말하십시오 new).하지만 코드를 단순하게 유지하고 싶었습니다.

C ++ 벡터 테스트 :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

C # 목록 테스트 :

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++-배열 :

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C #-배열 :

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

시간 : (릴리즈 / 디버그)

C ++

  • 600 / 606ms 어레이 초기화,
  • 200 / 270ms 배열 채우기,
  • 1 초 / 13 초 벡터 초기화 및 채우기.

(예, 13 초, 디버그 모드에서 항상 목록 / 벡터에 문제가 있습니다.)

씨#:

  • 20 / 20ms 어레이 초기화,
  • 403/440 ms 배열 채우기,
  • 710 / 742ms 목록 초기화 및 채우기.

1
std :: list에서 인덱스 접근자를보고 싶습니다. 어쨌든, 목록, 해제 모드에서는 37 초가 걸립니다. 디버깅하지 않고 해제 : 3 초 목록, 0,3 초 벡터. 아마도 역 참조 문제 또는 sth. 샘플 : nopaste.pl/12fb
Wiory

2
보다 정확한 측정을 위해서는을 사용하지 System.DateTime.Now말고 스톱워치 클래스 를 사용해야합니다 .
Sam

4
C ++에서 벡터에 대해 채우기 시간이 느린 이유 중 하나는 push_back을 사용하기 때문입니다. 이 방법은 at 메소드 나 연산자 []를 사용하는 것보다 속도가 느린 수많은 게시물에서 나타났습니다. 이러한 방법 중 하나를 사용하려면 크기 조정 또는 예약 방법을 사용해야합니다. 또한 c ++ 벡터 케이스의 초기화 시간이 오래 걸리는 이유는 복사 또는 할당 연산자 (이 경우 확실하지 않음)가 c ++ 벡터를 초기화하도록 강요하기 때문입니다. c ++의 배열에는 5001 대신 2 개의 새로운 호출을 사용하고 반복 속도가 빠른 알고리즘이 있습니다.
Zachary Kraus

5
나는 당신이 적절한 방식으로 C ++을하지 않았다고 생각합니다. 한 눈에 너무 많은 문제를 발견했습니다. 예를 들어 vector <vector <double >> myList = vector <vector <double >> ()
DAG

2
와. Lists와 크기 조정 가능한 배열을 비교하여 어떤 결론을 얻을 수 있는지 확실하지 않지만 이와 같은 벡터를 사용하려는 경우 reserve (), 내 친구, reserve ()에 대해 배우고 싶습니다.
U007D

3

글쎄요. 바이트 코드가 JIT뿐만 아니라 기계 코드로 변환 된 경우 (프로그램을 실행하면 의미합니다) 프로그램이 많은 할당 / 할당 해제를 사용하는 경우가 더 빨리하기 때문에 될 수 GC의 알고리즘은 하나 개의 통과가 필요합니다 (이론적으로) 전체 메모리를 한 번만 통과하지만 정상적인 malloc / realloc / free C / C ++ 호출은 모든 호출에서 오버 헤드를 유발합니다 (콜 오버 헤드, 데이터 구조 오버 헤드, 캐시 누락;).

따라서 이론적으로 가능합니다 (다른 GC 언어에서도 가능).

나는 사용할 수 없다는 극단적 인 단점을 실제로 보지 못합니다. 대부분의 프로그래머가 어쨌든 그것을 사용하지 않기 때문에 대부분의 응용 프로그램에서 C #으로 메타 프로그래밍 보지 못합니다.

또 다른 큰 장점은 LINQ "확장" 과 같은 SQL 이 컴파일러가 데이터베이스 호출을 최적화 할 수있는 기회를 제공한다는 것입니다 (즉, 컴파일러는 호출 된 함수가 인라인되거나 귀하의 사용을 위해 최적화되었지만 여기에서 추측하고 있습니다).


1
적절한 C ++ 개발자는 설명하는 문제에 부딪치지 않습니다. 자신의 프로그램에서 수업을 밟고 그것을 C ++이라고 부르기로 결정한 나쁜 C 프로그래머 만이 그러한 문제를 겪게됩니다.
더 명확한

1
신들의 사랑을 위해, 이것은 8 살입니다, OMFGz
Quonux

더 나은 최신 답변을
주시기 바랍니다

2

C #으로 작성된 응용 프로그램이 빠르게 실행되고 더 많은 C ++로 작성된 응용 프로그램이 빨리 실행되고 있다고 가정합니다 (C ++은 이전 버전
이지만 UNIX도 사용합니다 ...) -실제로 질문은-그게 뭐죠, 사용자 개발자들이 불평하고 있습니다 ...
IMHO, C #의 경우 UI가 매우 편안하고 라이브러리 계층이 훌륭하며 CLI의 전체 인터페이스 시스템이 있습니다. C ++의 경우 템플릿, ATL, COM, MFC 및 OpenGL, DirectX 등과 같은 이미 작성되고 실행되는 코드의 전체 내용이 있습니다 ... 잠깐만-쾅! 멈췄다).
C #에서 코드를 매우 간단하고 빠르게 작성하려면 (오류 가능성도 증가시키는 것을 잊지 마십시오. C ++의 경우 개발자는 메모리 누수에 대해 불평합니다. 크래쉬, DLL 간 호출 및 "DLL 지옥"문제- 새로운
언어로 라이브러리를 지원하고 교체 할 수 있습니다 ... 프로그래밍 언어에 더 많은 기술이있을수록 소프트웨어의 품질과 속도가 향상 될 것입니다.


2

더 빠른 코드를 작성하는 프로그래머, 현재 머신의 속도를 빠르게하는 것에 대해 더 잘 알고있는 프로그래머, 우연히도 정확한 저수준 및 결정론을 가능하게하는 적절한 도구를 사용하는 프로그래머 최적화 기술. 이러한 이유로 C # 대신 C / C ++를 사용하는 사람들이이 사람들입니다. 나는 이것을 사실로 진술 할 것입니다.


Notch는 마인 크래프트가 자신이 조작하는 데이터의 양을 고려하여 매우 빠르도록 코딩했습니다. 또한 C ++에서는 거의 불가능했던 비교적 짧은 시간 안에 대부분 한 손으로 코딩했습니다. 그래도 최적화 기술에 동의합니다. 코드를 두 배 빠르게 실행하는 데 10 배의 개발 시간이 더 필요한 경우에는 그만한 가치가 있습니다.
Bill K

2

내가 실수하지 않으면 C # 템플릿은 런타임에 결정됩니다. C ++의 컴파일 타임 템플릿보다 느려 야합니다.

그리고 다른 많은 사람들이 언급 한 다른 모든 컴파일 타임 최적화와 안전 부족으로 인해 더 빠른 속도를 의미 할 때 ...

C ++이 원시 속도와 최소 메모리 소비 측면에서 확실한 선택이라고 말하고 싶습니다. 그러나 이것은 또한 코드를 개발하고 메모리 누수 나 널 포인터 예외가 발생하지 않도록하는 데 더 많은 시간을 요구합니다.

평결:

  • C # : 더 빠른 개발, 더 느린 실행

  • C ++ : 느린 개발, 빠른 실행.


1

실제로 코드에서 수행하려는 작업에 따라 다릅니다. VB.NET, C # 및 관리되는 C ++간에 성능 차이가 있다는 것은 도시의 전설 일 뿐이라고 들었습니다. 그러나 적어도 문자열 비교에서 관리되는 C ++은 C #의 바지를 능가하고 VB.NET의 바지를 능가하는 것으로 나타났습니다.

언어 간 알고리즘 복잡성에 대한 철저한 비교를 한 적이 없습니다. 또한 각 언어의 기본 설정을 사용하고 있습니다. VB.NET에서는 변수 선언 등을 요구하는 설정을 사용하고 있습니다. 관리되는 C ++에 사용하는 코드는 다음과 같습니다. (이 코드는 매우 간단합니다). .NET 4.6.2가 설치된 Visual Studio 2013의 다른 언어에서도 동일하게 실행됩니다.

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}

1

성능 측면에서 C #과 C ++ 사이에는 몇 가지 주요 차이점이 있습니다.

  • C #은 GC / 힙 기반입니다. 할당 및 GC 자체는 메모리 액세스의 비 로컬 성으로 오버 헤드
  • C ++ 옵티마이 저는 수년에 걸쳐 매우 좋아졌습니다. JIT 컴파일러는 컴파일 시간이 제한되어 있고 전체 범위가 보이지 않기 때문에 동일한 수준을 달성 할 수 없습니다.

그 외에도 프로그래머 역량도 중요한 역할을합니다. 나는 값으로 전달 된 클래스가 인수로 전달되는 나쁜 C ++ 코드를 보았습니다. 수행중인 작업을 모르는 경우 실제로 C ++에서 성능을 악화시킬 수 있습니다.


0

> 결국 답은 어딘가에 있어야합니까? :)

음.

여러 답변에서 언급했듯이 질문이 답변이 아닌 답변으로 초대하는 방식으로 질문이 잘못 지정 되었습니다. 한 가지 방법 만 사용하려면 :

그리고 어떤 프로그램? 어떤 기계? 어떤 OS? 어떤 데이터 세트?


난 전적으로 동의합니다. 사람들이 일반적인 질문을 할 때 왜 정확한 답변 (63.5 %)을 기대하는지 궁금합니다. 나는 이런 종류의 질문에 대한 일반적인 대답이 없다고 생각합니다.
전화 : Steve

@callmesteve : 무슨 말인지 알지만 마지막 문장은 분필 보드 위의 프로그래머처럼 손톱처럼 들릴 것입니다.
Wouter van Nifterick

1
이것은 질문에 대답하지 않는 것으로 보이며, 더 많은 의견이나 의견을 읽습니다.
Tas

-13

이로부터 영감을 얻어, 나는 대부분의 프로그램에 필요한 일반적인 지시의 60 %로 빠른 테스트를했습니다.

C # 코드는 다음과 같습니다.

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

문자열 배열과 arraylist는 이러한 명령어를 포함하기 위해 의도적으로 사용됩니다.

C ++ 코드는 다음과 같습니다.

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

내가 사용한 입력 파일 크기는 40KB입니다.

결과는 다음과 같습니다.

  • C ++ 코드는 9 초 만에 실행되었습니다.
  • C # 코드 : 4 초 !!!

아, 그러나 이것은 Linux에서 ... C #이 Mono에서 실행되고 C ++는 g ++로 실행되었습니다 .

좋아, 이것이 Windows에서 얻은 것 – Visual Studio 2003 :

  • C # 코드는 9 초 안에 실행되었습니다.
  • C ++ 코드 – 370 초 !!!

7
다른 데이터 구조와 라이브러리 코드를 사용하고 있습니다. "370 초"는 끔찍한 것을 나타냅니다. 우연히 디버거에서 실행하지 않습니까? 사용중인 CSV 라이브러리의 성능이 사용중인 언어의 성능보다 흥미 롭습니다. 그 맥락에서 벡터를 사용하고 어떤 최적화를 사용했는지 질문합니다. 또한, iostream (특히 "myfile << * j <<", ";")은 적어도 일부 일반적인 구현에서 파일에 쓰는 다른 방법보다 훨씬 느리다는 것이 널리 알려져 있습니다.
Arafangion

6
마지막으로 C ++ 버전에서 더 많은 작업을 수행하고 있습니다. (왜 csvColumn, csvElement 및 csvLines를 지우시겠습니까?)
Arafangion

2
while 루프의 모든 반복은 std :: istream과 std :: vector 및 std :: string을 파괴하고 재구성합니다. while 본문은 모든 반복에서 범위를 벗어납니다. while 범위 내의 모든 변수는 모든 반복에서 파기 및 구성됩니다.
doug65536

1
C ++ 코드를 읽는 것처럼 하나의 파일에서 다른 파일로 복사하려고합니다. 파일 스트림, 문자열, 벡터 및 문자열 스트림 간의 복잡한 상호 작용을 사용하는 대신 입력 파일 스트림을 출력 파일 스트림에 복사했을 수 있습니다. 이것은 많은 시간과 메모리를 절약했을 것입니다.
Zachary Kraus

2
최신 SSD 및 성능 앱 전용 테스트를 수행하지 않는 한 속도 테스트를 수행하려면 메모리에있는 테스트를 수행하여 디스크 IO에 도달하지 마십시오. 키보드를 건드리지 않아도 컴퓨터가 디스크에 지속적으로 쓰기 때문에.
user3800527
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.