산술연산 과 비트연산의 속도에 대한 질문

exsider의 이미지

제가 듣기로는 산술연산 보다 비트연산이 빠르다고 하던데
산술연산 중에서 특히 *, /, % 와 &, | 를 비교했을 때 수행속도가 어느 정도나
차이가 나나요?

goodfiend의 이미지

기본적인 연산은 and, or, shift 정도 입니다. (물론 xor, nand, barrel shift 등등 여러가지 약간 복잡한 형태도 있긴 합니다만...)

산술연산은 저런 기본적인 연산을 조합해야 가능합니다.

비트연산보다 당연히 느리지요.

구체적인 성능은 연산을 어떻게 회로로 구성했느냐에 따라 다릅니다.

연산속도의 대략적인 측정은 간단한 프로그램을 많은 횟수 돌려보면 어렵지 않게 가능할겁니다.

직접 프로그램을 작성해보시거나 다른 사람이 테스트용으로 작성한 프로그램을 돌려보시면 얼마나 차이가 나는지 구체적으로 확인하실 수 있을겁니다.

lsj0713의 이미지

웬만하면 컴파일러를 믿으라고 말하겠습니다. 저런 종류의 최적화는 대부분의 경우 삽질입니다. 저런 식으로 얻는 효과는 대부분의 경우 극히 미미합니다.

essp77의 이미지

하드웨어에 따른 속도차이를 물어보신건지(8비트,16비트,32비트,64비트)..
아니면 단순히 산술연산과 비트연산을 물어보신건지...

8비트 cpu 로 , 16비트 연산을 하면 , 무자게 느립니다. 트릭을 쓰지 않고서는 원하는 바를 얻기 힘들정도로....

산술연산과 비트연산도 마찬가지 라고 생각합니다.

질문하신분이 , 8비트 가지고 16비트 연산을 했을때 차이가 나냐고 물으신다면
당근, 차이가 엄청 납니다.
마찬가지로 , 산술연산과 비트연산은 차이가 많이 납니다.

Necromancer의 이미지

복잡도는

가장 간단한건 and, or가 되고
그다음이 덧셈과 뺄셈, shift가 되며
젤로 복잡한게 곱셈과 나눗셈입니다. 특히 나눗셈 ㅠ.ㅠ

그래서 컴파일러 최적화 기법 중에 특정 값에 2나 4를 곱하거나 나누는
연산의 경우 이를 쉬프트로 바꿔 처리하는 기법도 있으니

Written By the Black Knight of Destruction

neohwang의 이미지

경우에 따라 좀 다르겠지만,

옛날 10여넌전 제가 386컴에서 테스트해 본 결과 한 50 ~ 100배 정도의 차이가 났습니다.

물론 비트연산이 쉽게되는 것이 있고, 그렇지 않은 경우가 있어서 정확히 말씀드리긴 뭐하지만,

하지만 요즘 컴퓨팅 파워가 워낙 좋아져서.. 그렇게 할 필요는 거의 없죠.

참고적으로.
그때는 dos에서 한글라이브러리 만들때 한 테스트 이고,

추가적으로
제가 테스트한 부분에서는 c언어와 assembly 언어의 속도차이는 100배가 나더군요.

ssehoony의 이미지

산술 연산을 최적화를 위해 비트연산으로 하는건 크게 속력향상을 가져오지 않습니다.

가령 일반적으로 가장 흔히 사용하는
*2 의 산술연산의 경우 << 1
*4 의 경우 << 2
/2 의 경우 >> 1
/4 의 경우 >> 2
뭐 이런식으로 (저거 비트연산 syntax가 맞나요?) 하면 빠르다고들 하자나요.

하지만 이렇게 하면 소스의 가독성이 많이 떨어지는 문제도 있고
또한 저런 정도의 기초 수준의 비트연산은 *2 하면 내부적으로
최신 컴파일러들은 << 1 로 계산해준다고 하더군요.

Necromancer의 이미지

옛날 통신망에 돌아다녔던 8086 cpu 스펙 문서를 보면 mul, div 명령은 한개당
50-200클럭을 잡아먹는다고 나와 있는 걸로 알고 있습니다. and, or나 add, sub 명령은
2클럭이었던가... 지금 그 스펙 문서가 없으니...

neohwang wrote:

옛날 10여넌전 제가 386컴에서 테스트해 본 결과 한 50 ~ 100배 정도의 차이가 났습니다.

Written By the Black Knight of Destruction

antibug의 이미지

예ㅤㄹㅡㄷ 들어 8051 (20년쯤 된 CPU입니다.)은 8비트 곱셈이 4클럭, 덧셈이
대개 1클럭, 비트 연산도 대개 1클럭입니다. 8086 시리즈도 이와 별 다를
바는 없는것으로 알고 있는데, 오퍼랜드(C <- A * B 에서 A나 B)중 하나를
메모리로 지정할 수 있기 때문에 실제 속도는 천차만별입니다. 더불어 당시
에는 캐시도 없었기 때문에 OP코드와 실행속도를 1대1로 비교할 수 있었
지만 지금은 그것도 불분명해집니다.

결국 그정도의 최적화로 얻을 수 있는 정도의 이득이 캐시 미스 한방으로
완전히 상쇄되고 남을 수도 있는거죠. 뭐, 운없으면 하드 스왑이라도...

다만, 임베디드쪽 (일반적으로 열악한 CPU 파워를 가지고 있는)에서는
그런걸 좀 생각해줄 필요가 있습니다. 예로 들었던 8051이나 각종 8비트
CPU들이죠. (16비트만 해도 요즘 대부분 캐시 들어가 있고 곱셈기 가지고
있어서 많아야 두배나 네배정도 일겁니다.) 하지만 제 생각에 그정도
최적화를 C로 하는 것보다는 차라리 그쪽만 따로 떼어서 어셈으로
가져가시는게 소스 가독성과 속도를 동시에 잡을 수 있을 것 같습니다.

--------------------------------------
재미없는 일은 하지 말자는 인간 쓰레기.
-.-;

plustag의 이미지

해묵은 쓰레드에 리플을 다는 이유는..

int 형 정수에 2^n의 연산을 할 때..

학교에서 비트연산과 산술연산의 차이를 비교해보라면서 프로그램을 짜게 만들었는데..

gettimeofday() 함수를 이용하여 시간을 비교하여 봤습니다..

당연히 비트연산이 더 빠를줄 알았는데(책에서도 빠르다고 나오고.. 당연히 빠른줄 알고 있었는데)

비트연산이 산술연산보다 3~4배정도 더 느립니다.

이게 어찌된 일일까요?

Shift operation
10 * 64 = 640
Shift operation time
34 usec
Arithmetic operation
10 * 64 = 640
7 usec

누구냐 넌?

익명사용자의 이미지

#include <stdio.h>
#include <sys/time.h>
 
int main()
{
        int a;
        struct timeval timea, timeb;
 
 
        a=10;
        printf("Shift operation\n");
 
        gettimeofday(&timea, NULL);
//      printf("%ld:%ld\n", timea.tv_sec, timea.tv_usec);
 
 
        printf("%d * 64 = %d\n", a, a<<6);
 
        gettimeofday(&timeb, NULL);
//    printf("%ld:%ld\n", timeb.tv_sec, timeb.tv_usec);
 
        printf("Shift operation time\n");
        printf("%ld usec\n", timeb.tv_usec-timea.tv_usec);
 
        a=10;
        printf("Arithmetic operation\n");
 
        gettimeofday(&timea, NULL);
//    printf("%ld:%ld\n", timea.tv_sec, timea.tv_usec);
 
        printf("%d * 64 = %d\n", a, a*64);
 
        gettimeofday(&timeb, NULL);
//    printf("%ld:%ld\n", timeb.tv_sec, timeb.tv_usec);
 
        printf("%ld usec\n", timeb.tv_usec-timea.tv_usec);
 
        return 0;
}

위처럼 코드를 짜셨던데 이것은 연산의 시간을 재는 프로그램이 아니라 printf 함수의 시간을 재는 프로그램입니다.
연산에 걸리는 시간이 printf 함수에 걸리는 시간에 비해서 너무나 작기 때문입니다.

하나의 연산에 걸리는 시간은 정확히 측정하기 어렵습니다.
shift나 곱하기나 모두 한 CPU 인스트럭션으로 처리되기 때문에 gettimeofday의 정확도 보다 더 작은 단위로 나올 수 있습니다.
대충이라도 보려면 연산을 수백 수천번 반복해서 그것의 시간을 재도록 하세요.

plustag의 이미지

감사합니다..

printf 함수 빼고 한 1000번 정도하니까 차이가 눈에 보이네요

누구냐 넌?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.