programing

C는 왜 이렇게 빠를까요?다른 언어는 왜 그렇게 빠르거나 빠르지 않을까요?

copyandpastes 2022. 7. 17. 22:23
반응형

C는 왜 이렇게 빠를까요?다른 언어는 왜 그렇게 빠르거나 빠르지 않을까요?

Stack Overflow 팟캐스트를 들을 때, "진짜 프로그래머"가 C로 쓰고, "머신에 가깝기 때문에" C가 훨씬 더 빠릅니다.앞의 주장을 다른 투고용으로 남겨두고, 다른 언어보다 빠른 C의 특별한 점은 무엇입니까?다른 말로 하자면, 다른 언어들이 C만큼 빠르게 실행되는 바이너리로 컴파일하는 것을 막는 방법은 무엇일까요?

C에 대해 특별한 것은 없습니다.그게 빠른 이유 중 하나예요.

가비지 컬렉션, 동적 타이핑 및 프로그래머가 프로그램을 쉽게 작성할 수 있는 기타 기능을 지원하는 새로운 언어입니다.

단점은 애플리케이션의 성능을 저하시키는 처리 오버헤드가 추가로 발생한다는 것입니다.C에는 이러한 기능이 없습니다.즉, 오버헤드는 없지만, 프로그래머는 메모리 리크를 방지하기 위해 메모리를 할당하고 해방할 수 있어야 하며 변수의 정적 입력에 대처해야 합니다.

즉, Java(Java Virtual Machine 포함)와 같은 많은 언어 및 플랫폼입니다.NET(공통 언어 런타임 포함)은 바이트 코드에서 네이티브 머신 코드를 생성하여 더 높은 성능을 달성하는 저스트 인 타임 컴파일과 같은 어드밴스를 통해 수년간 성능이 향상되었습니다.

C디자이너의 트레이드오프가 있습니다.즉, 안전보다 속도를 중시하는 결정을 내린 것입니다.C는 하지 않는다

  • 배열 인덱스 한계 확인
  • 초기화되지 않은 변수 값이 있는지 확인하십시오.
  • 메모리 누출 여부를 점검하십시오.
  • Null 포인터의 참조 해제 여부를 확인합니다.

어레이에 인덱싱할 때 Java에서는 가상 시스템에서 메서드 호출, 바인딩 검사 및 기타 건전성 검사가 필요합니다.그것은 타당하고 전적으로 괜찮다. 왜냐하면 그래야 할 곳에 안전을 더해주기 때문이다.하지만 C에서는 아주 사소한 것들도 안전하게 보관되지 않습니다.예를 들어 C는 복사할 영역이 겹치는지 확인하기 위해 memcpy를 필요로 하지 않습니다.대규모 비즈니스 애플리케이션을 프로그래밍하기 위한 언어로 설계되지 않았습니다.

그러나 이러한 설계 결정은 C 언어의 버그가 아닙니다.컴파일러나 라이브러리 라이터가 컴퓨터의 성능을 최대한 끌어낼 수 있도록 설계되어 있습니다.C의 정신은 다음과 같습니다.C의 이론적 근거에 의해 설명되고 있습니다.

C 코드는 포터블이 아닐 수 있습니다.프로그래머에게 진정한 휴대용 프로그램을 작성할 수 있는 기회를 주기 위해 노력했지만 위원회는 프로그래머에게 "고급 어셈블리"로서 C를 사용하는 것을 막기 위해 휴대성 있는 문서 작성을 강요하고 싶지 않았다. 기계 고유의 코드를 작성하는 능력은 C의 강점 중 하나이다.

C의 정신을 지켜라.위원회는 C의 전통적 정신을 보존하는 것을 주요 목표로 삼았다.C의 정신에는 많은 측면이 있지만 본질은 C언어의 기초가 되는 기본원칙의 공동체 정서이다.C의 정신의 일부 측면은 다음과 같은 문구로 요약될 수 있다.

  • 프로그래머를 믿으세요.
  • 프로그래머가 해야 할 일을 하는 것을 막지 마세요.
  • 언어를 작고 단순하게 유지하십시오.
  • 작업을 수행할 수 있는 방법은 한 가지뿐입니다.
  • 휴대성이 보장되지 않더라도 빠르게 만들어 주세요.

마지막 속담은 조금 설명이 필요하다.효율적인 코드 생성 가능성은 C의 가장 중요한 강점 중 하나입니다.매우 간단한 작업에 대해 코드 폭발이 발생하지 않도록 하기 위해 많은 작업이 일반적인 추상 규칙이 아닌 대상 시스템의 하드웨어가 이를 수행하는 방식으로 정의됩니다.이 머신의 동작에 대한 의지의 예는 표현식에서 사용하는 char 객체의 확대를 규정하는 규칙에서 볼 수 있습니다.char 객체의 값이 부호 있는 수량과 부호 없는 수량으로 확장되는지 여부는 일반적으로 타깃 머신에서 어떤 바이트 연산이 더 효율적인지에 따라 결정됩니다.

만약 당신이 C에서 0.05초만에 실행되는 무언가를 만들기 위해 한 달을 소비하고, 내가 자바에서 같은 것을 쓰는 데 하루를 소비한다면, 그것은 0.10초만에 실행된다면, C가 정말 더 빠를까요?

그러나 질문에 대답하자면, C 코드를 "잘" 쓰는 부분에는 기계 수준에 가까운 수동 최적화가 포함되어 있기 때문에 잘 작성된 C 코드가 다른 언어로 작성된 코드보다 일반적으로 더 빠르게 실행됩니다.

컴파일러는 매우 영리하지만 손으로 마사지하는 알고리즘과 경쟁하는 코드를 창조적으로 만들어 낼 수 없습니다('손'이 좋은 C 프로그래머의 것이라고 가정).

편집:

많은 댓글은 "C로 쓰고 최적화는 생각하지 않는다"는 식으로 쓰여져 있습니다.

그러나투고에서 구체적인 예를 들자면:

델파이에서는 이렇게 쓸 수 있었다.

function RemoveAllAFromB(a, b: string): string;
var
  before, after :string;
begin
  Result := b;
  if 0 < Pos(a,b) then begin
    before := Copy(b,1,Pos(a,b)-Length(a));
    after := Copy(b,Pos(a,b)+Length(a),Length(b));
    Result := before + after;
    Result := RemoveAllAFromB(a,Result);  //recursive
  end;
end;

C에는 이렇게 적습니다.

char *s1, *s2, *result; /* original strings and the result string */
int len1, len2; /* lengths of the strings */
for (i = 0; i < len1; i++) {
   for (j = 0; j < len2; j++) {
     if (s1[i] == s2[j]) {
       break;
     }
   }
   if (j == len2) {  /* s1[i] is not found in s2 */
     *result = s1[i]; 
     result++; /* assuming your result array is long enough */
   }
}

하지만 C 버전에는 몇 가지 최적화가 있습니까?델은 델파이 버전에서는 생각하지 않는 구현에 관한 많은 결정을 내립니다.문자열은 어떻게 구현됩니까?델파이에서는 안 보여요C에서는 문자라고 불리는 ASCII 정수 배열에 대한 포인터가 되기로 결정했습니다.C에서는 캐릭터의 존재를 한 번에 하나씩 테스트합니다.델파이에서는 포스를 사용합니다.

그리고 이것은 단지 작은 예에 불과합니다.큰 프로그램에서 C 프로그래머는 코드 몇 줄마다 이러한 낮은 수준의 결정을 내려야 합니다.수작업으로 최적화된 실행 파일이 추가됩니다.

아직 못 봤으니까 C가 더 빠른 경향이 있어요. 다른 거의C쓰여있거든요.

Java는 C, Python은 C(또는 Java, 또는 )에 구축됩니다.NET 등) Perl 등입니다.OS는 C, 가상 머신은 C, 컴파일러는 C, 인터프리터는 C로 작성됩니다.어떤 것들은 여전히 어셈블리 언어로 쓰여져 있는데, 이것은 훨씬 더 빠른 경향이 있다.점점 더 많은 것들이 다른 무언가로 쓰여지고 있는데, 그 자체가 C로 쓰여지고 있다.

다른 언어(어셈블리가 아닌)로 쓴 각 문은 일반적으로 C에서 여러 개의 문장으로 구현되며, 이 문장은 네이티브 기계 코드로 컴파일됩니다.이러한 다른 언어들은 C보다 더 높은 수준의 추상화를 얻기 위해 존재하는 경향이 있기 때문에 C에서 요구되는 추가 문장은 안전성, 복잡성 및 오류 처리 제공에 초점을 맞추는 경향이 있다.그것들은 종종 좋은 것들이지만, 그것들은 비용이 든다. 그리고 그것의 이름은 속도크기이다.

개인적으로, 저는 문자 그대로 대부분의 이용 가능한 영역에 걸쳐 수십 개의 언어로 글을 써왔습니다.그리고 개인적으로 여러분이 암시하는 마법을 찾고 있습니다.

어떻게 케이크를 먹고 먹을 수 있을까요?어떻게 하면 내가 좋아하는 언어로 높은 수준의 추상화를 가지고 놀다가 속도를 위해 C의 핵심까지 내려갈 수 있을까?

몇 년 동안 연구한 결과, Python(C의 경우)이 되었습니다.한 번 보는 게 좋을 거야덧붙여서 Python에서 Assembly로 드롭다운할 수도 있습니다(특수 라이브러리의 작은 도움).

반면에, 나쁜 코드는 어떤 언어로든 쓰여질있다.따라서 C(또는 어셈블리) 코드가 자동으로 빨라지는 은 아닙니다.마찬가지로 일부 최적화 트릭은 상위 언어 코드의 일부를 원시 C의 성능 수준에 근접시킬 수 있습니다.그러나 대부분의 어플리케이션에서는 프로그램은 대부분의 시간을 사람 또는 하드웨어에 대기하고 있기 때문에 차이는 그다지 중요하지 않습니다.

즐거운 시간 되세요.

C가 빠른 것이 아니라 C의 비용 모델이 투명하다.C 프로그램이 느리면 많은 문장을 실행함으로써 명백한 방식으로 느립니다.C의 운영 비용과 비교하여 객체(특히 리플렉션) 또는 문자열에 대한 높은 수준의 운영에는 명확하지 않은 비용이 발생할 수 있습니다.

일반적으로 C와 같은 속도의 바이너리로 컴파일되는 언어는 Standard ML(MLton 컴파일러 사용)과 Objective Caml입니다.벤치마크 게임을 보면 바이너리 트리 등 일부 벤치마크의 경우 OCaml 버전이 C보다 빠르다는 것을 알 수 있습니다(MLton 엔트리는 발견되지 않았습니다).하지만 총격전을 너무 심각하게 받아들이지 마세요.그것은 게임이라고 하는 것처럼 사람들이 코드를 조정하는데 얼마나 많은 노력을 기울였는지 보여주는 결과가 종종 있습니다.

거기에는 많은 질문들이 있다 – 대부분 내가 대답할 자격이 없는 질문들이다.하지만 이 마지막을 위해:

다른 언어들이 C만큼 빠르게 실행되는 바이너리로 컴파일하는 것을 막는 방법은 무엇일까요?

한마디로 추상화.

C는 기계어로부터 불과 1~2레벨의 추상화입니다.Java 와 를 참조해 주세요.인터넷 언어는 어셈블러에서 최소 3단계 추상화 단계에 있습니다.Python과 Ruby는 잘 모르겠어요.

일반적으로 프로그래머의 완구(복잡한 데이터 타입 등)가 많을수록 기계어와는 거리가 멀어져 번역을 더 많이 해야 합니다.

나는 여기 저기 있지만 그것이 기본적인 요지입니다.

업데이트 ------- 이 투고에는, 상세한 것에 관한 좋은 코멘트가 있습니다.

어셈블리 언어도 언어라는 것을 잊으신 것 같네요.

하지만 정말로, C 프로그램은 프로그래머가 자신이 무엇을 하고 있는지 알아야 더 빨라진다.같은 작업을 하는 다른 언어로 작성된 프로그램보다 느리게 실행되는 C 프로그램을 쉽게 작성할 수 있습니다.

C가 더 빠른 이유는 이렇게 설계되었기 때문입니다.컴파일러가 코드를 최적화하는 데 도움이 되는 많은 "저수준" 작업을 수행할 수 있습니다.또는 프로그래머가 코드를 최적화할 책임이 있다고 말할 수 있습니다.하지만 종종 상당히 까다롭고 오류가 발생하기 쉽습니다.

이미 언급한 다른 언어들과 마찬가지로 다른 언어들도 프로그래머의 생산성에 더 초점을 맞추고 있습니다.일반적으로 프로그래머 시간은 기계 시간보다 훨씬 더 비싸다고 믿고 있습니다(옛날에도 마찬가지).따라서 프로그래머가 프로그램 실행 시간이 아닌 프로그램 작성 및 디버깅에 소비하는 시간을 최소화하는 것이 매우 합리적입니다.그러기 위해서는 많은 것이 자동화되어 있기 때문에 프로그램을 보다 빠르게 하기 위해 할 수 있는 일에 약간의 희생을 감수해야 합니다.

많은 사람들이 장황하게 말해왔다는 것을 알지만,

C는 (고객에게) 효과가 적기 때문에 더 빠릅니다.

주요 요인은 그것이 정적으로 입력된 언어이고 기계어로 컴파일된다는 것입니다.또한, 낮은 수준의 언어이기 때문에, 일반적으로 당신이 말하지 않는 것은 하지 않습니다.

이것들은 생각나는 다른 요인들이다.

  • 변수가 자동으로 초기화되지 않음
  • 어레이 검사 한계 없음
  • 선택되지 않은 포인터 조작
  • 정수 오버플로 체크 없음
  • 정적 유형 변수
  • 함수 콜은 스태틱입니다(함수 포인터를 사용하지 않는 한).
  • 컴파일러 라이터는 최적화 코드를 개선하기 위해 많은 시간을 들여 왔습니다.또한 사람들은 최고의 성능을 얻기 위해 C에서 프로그램을 하기 때문에 코드를 최적화해야 한다는 압박감이 있습니다.
  • 언어 사양의 일부는 구현 정의되어 있기 때문에 컴파일러는 최적의 방법으로 작업을 수행할 수 있습니다.

대부분의 정적 타입의 언어는 특히 포인터 에일리어싱 등으로 인해 C가 할 수 없는 것을 가정할 수 있는 경우 C보다 빠를 수도 있고 빠르게 컴파일할 수도 있습니다.

C++가 평균보다 빠릅니다(처음처럼 C의 슈퍼셋이 대부분이지만 약간의 차이는 있습니다).그러나 특정 벤치마크의 경우 더 빠른 다른 언어가 있는 경우가 많습니다.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/

fannjuch-redux스칼라에서 가장 빠른

n-body그리고.fasta에이다가 더 빨랐어요

spectral-norm포트란에서 가장 빨랐어요

reverse-complement,mandelbrot그리고.pidigitsATS에서 가장 빨랐습니다.

regex-dnaJavaScript에서 가장 빠릅니다.

chameneou-redux자바7이 가장 빨랐어요

thread-ring해스켈에서 가장 빨랐어요

나머지 벤치마크는 C 또는 C++에서 가장 빨랐습니다.

대부분의 경우, 모든 C 명령은 극소수의 어셈블러 명령에 대응합니다.기본적으로는 더 높은 수준의 기계 코드를 쓰기 때문에 프로세서가 수행하는 거의 모든 작업을 제어할 수 있습니다.C++와 같은 다른 컴파일 언어에는 생각보다 훨씬 더 많은 코드가 될 수 있는 단순해 보이는 명령어가 많이 있습니다(가상 함수, 복사 생성자 등).Java나 Ruby와 같은 인터프리터 언어에는 전혀 볼 수 없는 명령 레이어가 있습니다.가상 머신이나 인터프리터입니다.

다음과 같은 여러 가지 이유가 있습니다.

  • 어셈블리 언어로 컴파일됩니다.
  • 정적으로 입력됩니다.
  • 가비지 컬렉션이 없습니다.
  • 예외 메커니즘은 없습니다.
  • 컴파일러 최적화
  • C의 철학 중 일부는 기능을 추가하는 대신 단순하게 유지하고 하위 호환성을 유지하는 것입니다.

핫스팟 최적화, 사전 컴파일된 메타 알고리즘 및 다양한 형태의 병렬 처리와 같은 고급 최적화 기술은 차치하고라도 언어의 기본 속도는 내부 루프 에서 일반적으로 지정되는 작업을 지원하기 위해 필요한 암묵적인 백그라운드 복잡성과 강하게 상관됩니다.

아마도 가장 분명한 것은 간접 메모리 참조에 대한 유효성 검사일 것입니다. 예를 들어 포인터 검사와 같은null어레이 경계에 대해 인덱스를 체크합니다.대부분의 고급 언어는 암묵적으로 이러한 검사를 수행하지만 C는 수행하지 않습니다.그러나 이것이 반드시 이러한 다른 언어의 근본적인 제한은 아닙니다.충분히 똑똑한 컴파일러는 루프 불변 코드 모션을 통해 알고리즘의 내부 루프에서 이러한 체크를 제거할 수 있습니다.

C(및 밀접하게 관련된 C++)의 보다 근본적인 장점은 스택 기반 메모리 할당에 대한 의존도가 높다는 것입니다.이것은 본질적으로 할당, 할당 해제 및 액세스가 고속입니다.C(및 C++)에서는 프라이머리 콜스택을 사용하여 프리미티브, 어레이 및 집약(aggregate)을 할당할 수 있습니다.struct/class).

C는 임의의 크기 및 라이프 타임의 메모리를 동적으로 할당할 수 있는 기능을 제공하지만(이른바 '히프'를 사용), 디폴트로는 할당하지 않습니다(스택이 대신 사용됩니다).

감질나게 C 메모리 할당 전략을 다른 프로그래밍 언어의 런타임 환경 내에서 복제할 수 있습니다.이는 C 또는 C++로 작성된 코드를 JavaScript의 서브셋으로 변환하여 웹 브라우저 환경에서 거의 네이티브 속도로 안전하게 실행할 수 있는 asm.js에 의해 입증되었습니다.


한편, C와 C++가 대부분의 다른 언어를 능가하는 속도 분야는 네이티브 머신 명령어 세트와 심리스하게 통합할 수 있는 능력입니다.이것의 주목할 만한 예는 (컴파일러와 플랫폼에 의존한) SIMD 내장 기능의 가용성입니다.이는 현재 거의 유비쿼터스한 병렬처리 하드웨어를 활용하는 커스텀 알고리즘의 구축을 지원하면서도 언어에 의해 제공되는 데이터 할당 추상화(저레벨 레지스터 할당은 m)입니다.컴파일러에 의해 이전됩니다).

코드의 퍼포먼스에 중요한 부분에서 C와 선택한 언어 모두에 대한 디스어셈블리를 참조해 주세요. Visual Studio 런타임에 디스어셈블리 창을 통해 디스어셈블리를 확인하시면 될 것 같습니다.Net. Java에서 windbg를 사용하는 경우 까다롭다면 가능합니다.단, 를 사용하는 경우에는 가능합니다.많은 이슈들이 똑같을 것이다.

필요없을 때는 C로 쓰는 것을 좋아하지 않지만, 특히 퍼포먼스 크리티컬 어플리케이션에서 공통적으로 많은 데이터가 관련되어 있는 경우 C 이외의 언어의 속도를 강조하기 위해 C에서 동일한 루틴을 분해하는 것만으로 충분히 해소할 수 있다고 생각합니다.Fortran은 전문 분야에서는 예외일 수 있습니다.C보다 높은 레벨인가요?

처음 J를 비교했을 때IT 코드와 네이티브 코드를 조합하여 해결했습니다.넷 코드는 C 코드와 비슷하게 실행될 수 있습니다.추가적인 추상화 수준과 모든 안전 점검에는 상당한 비용이 수반됩니다.Java에도 같은 비용이 적용될 수 있지만, 내 말을 믿지 말고 성능이 중요한 곳에서 사용해 보십시오.(J에 대해 충분히 아는 사람이 있나요?메모리에서 컴파일된 프로시저를 검색하기 위해 Java를 사용했습니까?당연히 가능하겠지요)

링크에서 왜 어떤 언어는 빠르고 어떤 언어는 느린지에 대한 답변을 찾았습니다.C 또는 C++가 다른 언어보다 빠른지 더 잘 알 수 있기를 바랍니다.C보다 빠른 언어도 있지만 모든 언어를 사용할 수는 없습니다.몇 가지 설명 -

Fortran이 여전히 중요한 이유 중 하나는 Fortran으로 작성된 숫자 계산 루틴이 대부분의 다른 언어로 작성된 동등한 루틴보다 더 빠르기 때문입니다.이 분야에서 Fortran과 경쟁하고 있는 언어(C 및 C++)가 사용되고 있는 것은 이 퍼포먼스와 경쟁하고 있기 때문입니다.

이 때문에, 「왜?」라고 하는 의문이 생깁니다.C++와 Fortran이 빠른 이유는 무엇이며, Java나 Python과 같은 다른 인기 언어보다 성능이 뛰어난 이유는 무엇입니까?

해석과 컴파일 프로그래밍 언어가 권장하는 프로그래밍 스타일과 기능에 따라 프로그래밍 언어를 분류하고 정의하는 방법은 다양합니다.퍼포먼스를 볼 때 가장 큰 차이는 통역된 언어와 컴파일된 언어 간의 차이입니다.

그 차이는 어렵지 않다; 오히려 스펙트럼이 있다.한쪽 끝에는 Fortran, C 및 C++를 포함하는 그룹인 기존의 컴파일 언어가 있습니다.이러한 언어에는 프로그램의 소스 코드를 프로세서가 사용할 수 있는 실행 가능한 형식으로 변환하는 개별 컴파일 단계가 있습니다.

이 컴파일 프로세스에는 몇 가지 단계가 있습니다.소스 코드가 분석 및 해석됩니다.이 시점에서 오타나 철자 오류와 같은 기본적인 코딩 오류를 발견할 수 있습니다.해석된 코드는 메모리 내 표현을 생성하기 위해 사용되며, 이 표현은 실수의 검출에도 사용할 수 있습니다.이번에는 존재하지 않는 함수를 호출하거나 텍스트 문자열에 대해 산술 연산을 수행하려고 하는 등의 의미 오류입니다.

그런 다음 이 메모리 내 표현을 사용하여 실행 가능한 코드를 생성하는 부분인 코드 생성기를 구동합니다.생성된 코드의 성능을 개선하기 위해 코드 최적화는 이 프로세스 내에서 여러 번 수행됩니다. 코드 표현에 대해 높은 수준의 최적화를 수행할 수 있으며 코드 생성기의 출력에 낮은 수준의 최적화를 사용할 수 있습니다.

실제로 코드를 실행하는 것은 나중에 이루어집니다.전체 컴파일 프로세스는 단순히 실행할 수 있는 무언가를 만드는 데 사용됩니다.

반대편에는 통역이 있습니다.인터프리터는 컴파일러와 유사한 해석 단계를 포함하지만, 이 단계는 프로그램이 즉시 실행되도록 직접 실행을 유도하기 위해 사용됩니다.

가장 심플한 인터프리터에는 언어가 지원하는 다양한 기능에 대응하는 실행 가능한 코드가 포함되어 있기 때문에 번호를 추가하거나 문자열을 결합하거나 특정 언어를 포함하는 기능을 사용할 수 있습니다.코드를 해석할 때 해당 함수를 검색하여 실행합니다.프로그램에서 생성된 변수는 이름에 데이터를 매핑하는 일종의 룩업 테이블에 저장됩니다.

인터프리터 스타일의 가장 극단적인 예는 배치 파일이나 셸 스크립트입니다.이러한 언어에서는 실행 가능한 코드가 인터프리터 자체에 내장되어 있지 않고 독립된 독립 실행형 프로그램에 내장되어 있는 경우가 많습니다.

이것이 퍼포먼스에 영향을 미치는 이유는 무엇일까요?일반적으로 각 간접 레이어는 성능을 저하시킵니다.예를 들어, 2개의 숫자를 추가하는 가장 빠른 방법은 프로세서의 레지스터에 두 숫자를 모두 넣고 프로세서의 추가 명령을 사용하는 것입니다.이것이 컴파일된 프로그램이 할 수 있는 일입니다.변수를 레지스터에 넣고 프로세서 명령을 이용할 수 있습니다.그러나 인터프리터드 프로그램에서는 동일한 추가를 위해 추가할 값을 가져오기 위해 변수 테이블에서 두 개의 룩업이 필요할 수 있으며, 그 후 함수를 호출하여 추가를 수행해야 합니다.이 함수는 컴파일된 프로그램이 실제 추가를 수행하기 위해 사용하는 것과 동일한 프로세서 명령을 사용할 수 있지만 명령을 실제로 사용하기 전에 추가 작업을 수행하면 작업이 느려집니다.

자세한 것은, 출처를 확인해 주세요.

1) 남들이 말한 것처럼 C는 당신에게 도움이 되지 않습니다.초기화 변수 없음, 어레이 경계 확인 없음, 메모리 관리 없음 등다른 언어의 이러한 기능에는 C가 소비하지 않는 메모리와 CPU 사이클 비용이 듭니다.

2) C는 추상화가 적고, 따라서 빠르다는 답변은 절반밖에 없다고 생각합니다.엄밀히 말하면, 언어 X의 「충분히 고도의 컴파일러」가 있는 경우, 언어 X는 C의 속도에 가깝거나 같은 것이 됩니다.C와의 차이점은 (아키텍처 코스를 수강한 경우) 매우 명백하고 어셈블리 언어에 직접 매핑되기 때문에 순진한 컴파일러도 제대로 할 수 있다는 것입니다.Python과 같은 경우에는 가능한 오브젝트 유형을 예측하고 머신 코드를 즉시 생성하기 위해 매우 고급 컴파일러가 필요합니다.C의 시멘틱스는 단순한 컴파일러로 충분합니다.

이들 답변의 대부분은 C가 (일반적인 시나리오 또는 특정 시나리오 중 하나) 더 빠르거나 그렇지 않은 이유에 대한 타당한 이유를 제시합니다.부정할 수 없는 것은, 다음과 같습니다.

  • 다른 많은 언어들은 우리가 당연하게 여기는 자동 기능을 제공합니다.예를 들어 경계 검사, 런타임 유형 검사, 자동 메모리 관리 등은 무료로 제공되지 않습니다.이러한 기능에는 적어도 어느 정도의 비용이 소요됩니다.이러한 기능을 사용하는 코드를 작성할 때는, 생각하지도, 깨닫지도 못할 수도 있습니다.
  • 소스로부터 머신으로의 이행은, C의 경우와 같이, 다른 언어에서는 직접적이지 않은 경우가 많습니다.
  • OTOH, 컴파일된 C 코드가 다른 언어로 작성된 다른 코드보다 빠르게 실행된다고 하는 것은 항상 사실이 아닌 일반화입니다.반례는 쉽게 찾을 수 있다(또는 고안할 수 있다).

그럼에도 불구하고, 다른 어떤 요소보다 C와 다른 많은 언어의 비교 성능에 큰 영향을 미친다는 것을 깨달았습니다.To Wit :

다른 언어에서는 더 느리게 실행되는 코드를 쉽게 작성할 수 있습니다.언어의 디자인 철학에 의해 격려되는 경우도 종종 있습니다.결과: C 프로그래머는 불필요한 작업을 수행하지 않는 코드를 쓸 가능성이 높습니다.

예를 들어 단일 메인창이 생성되는 단순한 Windows 프로그램을 생각해 보겠습니다.C 버전에서는, 다음의 정보가 입력됩니다.WNDCLASS[EX]전달되는 구조RegisterClass[Ex]를 호출합니다.CreateWindow[Ex]메시지 루프를 입력합니다.매우 단순하고 생략된 코드는 다음과 같습니다.

WNDCLASS wc;
MSG      msg;

wc.style         = 0;
wc.lpfnWndProc   = &WndProc;
wc.cbClsExtra    = 0;
wc.cbWndExtra    = 0;
wc.hInstance     = hInstance;
wc.hIcon         = NULL;
wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName  = NULL;
wc.lpszClassName = "MainWndCls";

RegisterClass(&wc);

CreateWindow("MainWndCls", "", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
             CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

while(GetMessage(&msg, NULL, 0, 0)){
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

C#의 동등한 프로그램은 코드 한 줄에 불과합니다.

Application.Run(new Form());

이 한 줄의 코드는 거의 20줄의 C코드가 했던 모든 기능을 제공하며, 에러 체크 등 우리가 빠뜨린 몇 가지를 추가한다.(일반적인 C프로젝트에서 사용되는 라이브러리보다) 더 풍부하고 완전한 라이브러리는 우리에게 많은 일을 해주었고, 우리에게 짧은 것처럼 보이지만 뒤에서 많은 절차를 수반하는 코드 조각들을 쓸 수 있는 시간을 확보했습니다.

하지만 쉽고 빠른 코드 분해를 가능하게 하는 풍부한 라이브러리는 제 요점이 아닙니다.내 요점은 우리의 작은 원라이너가 실제로 실행되었을 때 실제로 무슨 일이 일어나는지 조사하기 시작할 때 더 명확해 진다.나중에 재미삼아 활성화합니다.Visual Studio 2008 이상에서 NET 소스 액세스를 수행하고 위의 간단한 한 줄에 대해 설명합니다.우연히 보게 될 재미난 작은 보석 중 하나는 이 댓글입니다.Control.CreateParams:

// In a typical control this is accessed ten times to create and show a control.
// It is a net memory savings, then, to maintain a copy on control.
// 
if (createParams == null) {
    createParams = new CreateParams(); 
} 

번이요.이 정보는 데이터 저장에 저장되어 있는 정보의 합계와 거의 동일합니다.WNDCLASSEX구조 및 전달되는 것CreateWindowEx에서 취득됩니다.Control저장되기 전에 10회 수업WNDCLASSEX구조화 및 전달RegisterClassEx그리고.CreateWindowEx.

전체적으로 이 매우 기본적인 작업을 수행하기 위해 실행되는 명령의 수는 C보다 C#에서 2~3배 더 많습니다.이 이유의 일부는 기능이 풍부한 라이브러리를 사용하기 때문입니다.이 라이브러리는 반드시 일반화되어 있습니다.단순한 C코드는 우리가 필요로 하는 것만 하고 그 이상은 아무것도 하지 않습니다.그러나 그 중 일부는 의 모듈화된 객체 지향적 특성 때문입니다.NET 프레임워크는 절차적 접근법에 의해 종종 회피되는 많은 실행 반복에 적합합니다.

C#이나 를 괴롭히려는 것은 아닙니다.NET 프레임워크모듈화, 일반화, 라이브러리/언어 기능, OOP 등이 나쁜 것이라고 말하는 것도 아닙니다.개발의 대부분은 C에서, 나중에는 C++에서, 그리고 최근에는 C#에서 했습니다.마찬가지로 C 이전에는 조립품을 주로 사용했습니다.또, 한층 더 「높은」스텝을 밟을수록, 보다 좋은, 보다 유지보수가 용이한, 보다 견고한 프로그램을 단시간에 작성할 수 있게 됩니다.그러나 실행 속도가 좀 더 느린 경향이 있습니다.

C는 네이티브하게 컴파일된 낮은 수준의 언어이기 때문에 속도가 빠릅니다.하지만 C가 가장 빠르지 않다.재귀적 피보나치 벤치마크를 통해 Rust, Crystal 및 Nim의 속도를 높일 수 있습니다.

언어보다는 도구와 라이브러리가 중요합니다.C에서 사용할 수 있는 라이브러리와 컴파일러는 새로운 언어보다 훨씬 오래되었습니다.이렇게 하면 속도가 느려진다고 생각하실 수도 있지만, 전혀 반대입니다.

이러한 라이브러리는 처리 능력과 메모리가 부족할 때 작성되었습니다.그들은 일을 하기 위해서는 매우 효율적으로 쓰여져야만 했다.C 컴파일러 개발자들은 또한 다양한 프로세서를 위한 모든 종류의 현명한 최적화 작업을 하는 데 오랜 시간이 걸렸습니다.C의 성숙도와 폭넓은 채택은 동시대 다른 언어에 비해 큰 이점을 가져다 줍니다.또한 C가 필요로 하는 만큼 원시 성능을 강조하지 않는 새로운 도구에 비해 C의 속도가 더 우수합니다.

자동과 수동의 차이입니다. 상위 레벨의 언어는 추상화되므로 자동화됩니다.C/C++는 수동으로 제어 및 처리되며, 에러 체크 코드도 수작업이 될 수 있습니다.

C와 C++도 컴파일된 언어입니다.즉, 비즈니스 어디에서나 실행할 수 있는 것은 아닙니다.이러한 언어는 사용하는 하드웨어에 맞추어 미세 조정되어 gotcha의 레이어를 추가할 필요가 있습니다.C/C++ 컴파일러가 모든 플랫폼에 걸쳐 보편화됨에 따라 이 문제는 다소 완화되고 있습니다.플랫폼 간에 교차 컴파일을 수행할 수 있습니다.컴파일러 A가 컴파일러 B에 대해 동일한 코드를 다른 아키텍처로 컴파일하도록 지시하는 것은 아직 모든 곳에서 실행되는 상황은 아닙니다.

C언어는 이해하기 쉽거나 이해하기 쉽다고는 할 수 없기 때문에 시스템 언어라고 불립니다.그들은 이 모든 고도의 추상화 난센스 앞에 나타났다.이러한 이유로 프런트엔드 웹 프로그래밍에는 사용되지 않습니다.그들은 단지 작업에 적합하지 않고, 기존의 언어 도구로는 해결할 수 없는 복잡한 문제를 해결하기 위한 수단입니다.

이것이 바로 C와 C++가 매우 적합한 것(마이크로 아키텍처, 드라이버, 양자 물리학, AAA 게임, 운영 체제)과 같은 놀라운 것들을 얻을 수 있는 이유입니다.속도와 숫자에 대한 경계가 주요 분야입니다.

C is not always faster.

C is slower than, for example Modern Fortran.

C is often slower than Java for some things. ( Especially after the JIT compiler has had a go at your code)

C lets pointer aliasing happen, which means some good optimizations are not possible. Particularly when you have multiple execution units, this causes data fetch stalls. Ow.

The assumption that pointer arithmetic works really causes slow bloated performance on some CPU families (PIC particularly!) It used to suck the big one on segmented x86.

Basically, when you get a vector unit, or a parallelizing compiler, C stinks and modern Fortran runs faster.

C programmer tricks like thunking ( modifying the executable on the fly) cause CPU prefetch stalls.

You get the drift ?

And our good friend, the x86, executes an instruction set that these days bears little relationship to the actual CPU architecture. Shadow registers, load-store optimizers, all in the CPU. So C is then close to the virtual metal. The real metal, Intel don't let you see. (Historically VLIW CPU's were a bit of a bust so, maybe that's no so bad.)

If you program in C on a high-performance DSP (maybe a TI DSP ?), the compiler has to do some tricky stuff to unroll the C across the multiple parallel execution units. So in that case C isn't close to the metal, but it is close to the compiler, which will do whole program optimization. Weird.

And finally, some CPUs (www.ajile.com) run Java bytecodes in hardware. C would a PITA to use on that CPU.

It's all about time and effort.

Given an infinite amount of time and effort:

  • An assembly program will be faster than one written in C.
  • A C program will be faster than one written in C++.

Given an fixed amount of time and effort:

  • A C++ program will be faster than one written in C.
  • A C program will be faster than one written in Assembly.

Why? Because the more abstraction you do, the more time you can spend optimising the critical sections of code that really matter. A couple of assumptions here is a developer is equally competent in all three languages, you don't care about binary size, memory usage, etc.

Every abstraction has a cost performance-wise but should make code easier and faster to write.

what's to stop other languages from being able to compile down to binary that runs every bit as fast as C?

Nothing. Modern languages like Java or .NET langs are oriented more on programmer productivity rather than performance. Hardware is cheap now days. Also compilation to intermediate representation gives a lot of bonuses such as security, portability etc. .NET CLR can take advantage of different hardware - for example you don't need to manually optimize/recompile program to use SSE instructions set.

I don't think anyone has mentioned the fact that much more effort has been put into C compilers than any other compiler, with perhaps the exception of Java.

C is extremely optimize-able for many of the reasons already stated - more than almost any other language. So if the same amount of effort is put into other language compilers, C will probably still come out on top.

I think there is at least one candidate language that with effort could be optimized better than C and thus we could see implementations that produce faster binaries. I'm thinking of digital mars D because the creator took care to build a language that could potentially be better optimized than C. There may be other languages that have this possibility. However I cannot imagine that any language will have compilers more than just a few percent faster than the best C compilers. I would love to be wrong.

I think the real "low hanging fruit" will be in languages that are designed to be EASY for humans to optimize. A skilled programmer can make any language go faster - but sometimes you have to do ridiculous things or use unnatural constructs to make this happen. Although it will always take effort, a good language should produce relatively fast code without having to obsess over exactly how the program is written.

It's also important (at least to me) that the worst case code tends to be fast. There are numerous "proofs" on the web that Java is as fast or faster than C, but that is based on cherry picking examples. I'm not big fan of C, but I know that ANYTHING I write in C is going to run well. With Java it will "probably" run within 15% of the speed, usually within 25% but in some cases it can be far worse. Any cases where it's just as fast or within a couple of percent are usually due to most of the time being spent in the library code which is heavily optimized C anyway.

This is actually a bit of a perpetuated falsehood. While it is true that C programs are frequently faster, this is not always the case, especially if the C programmer isn't very good at it.

One big glaring hole that people tend to forget about is when the program has to block for some sort of IO, such as user input in any GUI program. In these cases, it doesn't really matter what language you use since you are limited by the rate at which data can come in rather than how fast you can process it. In this case, it doesn't matter much if you are using C, Java, C# or even Perl; you just cannot go any faster than the data can come in.

The other major thing is that using garbage collection and not using proper pointers allows the virtual machine to make a number of optimizations not available in other languages. For instance, the JVM is capable of moving objects around on the heap to defragment it. This makes future allocations much faster since the next index can simply be used rather than looking it up in a table. Modern JVMs also don't have to actually deallocate memory; instead, they just move the live objects around when they GC and the spent memory from the dead objects is recovered essentially for free.

This also brings up an interesting point about C and even more so in C++. There is something of a design philosophy of "If you don't need it, you don't pay for it." The problem is that if you do want it, you end up paying through the nose for it. For instance, the vtable implementation in Java tends to be a lot better than C++ implementations, so virtual function calls are a lot faster. On the other hand, you have no choice but to use virtual functions in Java and they still cost something, but in programs that use a lot of virtual functions, the reduced cost adds up.

The lack of abstraction is what makes C faster. If you write an output statement you know exactly what is happening. If you write an output statement in java it is getting compiled to a class file which then gets run on a virtual machine introducing a layor of abstraction. The lack of object oriented features as a part of the language also increases it's speed do to less code being generated. If you use C as an object oriented language then you are doing all the coding for things such as classes, inharitence, etc. This means rather then make something generalized enough for everyone with the amount of code and the performance penelty that requires you only write what you need to get the job done.

Amazing to see the old "C/C++ must be faster than Java because Java is interpreted" myth is still alive and kicking. There are articles going back a few years, as well as more recent ones, that explain with concepts or measurements why this simply isn't always the case.

Current virtual machine implementations (and not just the JVM, by the way) can take advantage of information gathered during program execution to dynamically tune the code as it runs, using a variety of techniques:

  • rendering frequent methods to machine code,
  • inlining small methods,
  • adjustment of locking

and a variety of other adjustments based on knowing what the code is actually doing, and on the actual characteristics of the environment in which it's running.

The fastest running code would be carefully hand crafted machine code. Assembler will be almost as good. Both are very low level and it takes a lot of writing code to do things. C is a little above assembler. You still have the ability to control things at a very low level in the actual machine, but there is enough abstraction make writing it faster and easier then assembler. Other languages such as C# and JAVA are even more abstract. While Assembler and machine code are called low level languages, C# and JAVA (and many others) are called high level languages. C is sometimes called a middle level language.

Back in the good ole days, there were just two types of languages: compiled and interpreted.

Compiled languages utilized a "compiler" to read the language syntax and convert it into identical assembly language code, which could than just directly on the CPU. Interpreted languages used a couple of different schemes, but essentially the language syntax was converted into an intermediate form, and then run in a "interpreter", an environment for executing the code.

Thus, in a sense, there was another "layer" -- the interpreter -- between the code and the machine. And, as always the case in a computer, more means more resources get used. Interpreters were slower, because they had to perform more operations.

More recently, we've seen more hybrid languages like Java, that employ both a compiler and an interpreter to make them work. It's complicated, but a JVM is faster, more sophisticated and way more optimized than the old interpreters, so it stands a much better change of performing (over time) closer to just straight compiled code. Of course, the newer compilers also have more fancy optimizing tricks so they tend to generate way better code than they used to as well. But most optimizations, most often (although not always) make some type of trade-off such that they are not always faster in all circumstances. Like everything else, nothing comes for free, so the optimizers must get their boast from somewhere (although often times it using compile-time CPU to save runtime CPU).

Getting back to C, it is a simple language, that can be compiled into fairly optimized assembly and then run directly on the target machine. In C, if you increment an integer, it's more than likely that it is only one assembler step in the CPU, in Java however, it could end up being a lot more than that (and could include a bit of garbage collection as well :-) C offers you an abstraction that is way closer to the machine (assembler is the closest), but you end up having to do way more work to get it going and it is not as protected, easy to use or error friendly. Most other languages give you a higher abstraction and take care of more of the underlying details for you, but in exchange for their advanced functionality they require more resources to run. As you generalize some solutions, you have to handle a broader range of computing, which often requires more resources.

Paul.

Some C++ algorithms are faster than C, and some implementations of algorithms or design patterns in other languages can be faster than C.

When people say that C is fast, and then move on to talking about some other language, they are generally using C's performance as a benchmark.

ReferenceURL : https://stackoverflow.com/questions/418914/why-is-c-so-fast-and-why-arent-other-languages-as-fast-or-faster

반응형