memcpy함수와 memmove함수에 대해서 정확히 알고 싶습니다.

kknd345의 이미지

제가 memmove 함수를 잘 몰라서 memcpy를 이용해서 레코드 삭제를 했습니다.

레코드 개수가 많은 관계로 for 돌려서 옮기는게 memcpy 보다 코드측면에서 복잡해 보여서...
( 큰 용량의 메모리 복사일시 for 문 돌리는거와 memcpy 성능 차이 나나요? )

레코드 4 레코드 3 레코드 2 레코드 1

이라고 했을때

레코드 2 삭제하면

memcpy( 레코드3 포인터, 레코드4 포인터 , sizeof(레코드*(4-2) ));

이런식으로 했는데...

결과는 이상 없습니다.

그런데 여기서 의문이 든게... 메모리 복사가 앞쪽부터 일어난다면 분명히 같은내용이 여러번 쓰여질거 같은데...

레코드 4가 레코드 3 위치에 복사가 되고
레코드 3위치에는 레코드4가 적혔으니 레코드 2위치에 레코드 4내용이 한번 더 적혀버리는....

memcpy 는 뒤에서부터 메모리 복사를 하나요?

그럼 이런문제에 안 부딪히는 memmove 동작 원리는 어떤가요?

ssehoony의 이미지

memcpy 는 앞(낮은주소)에서 뒤(높은주소)로 옮겨 가면서 복사하는 것이 일반 적인 구현입니다.
하지만 그 반대로 구현하더라도 memcpy 의 작동에는 이상이 없으므로 어떻게 구현이 되어 있던 상관은 없습니다.
중요한것은, memcpy는 복사대상과 복사원본의 주소공간이 서로 겹치지 않아야 한다는 것이지요.

kknd345님의 경우는 메모리 주소 공간이 서로 겹쳐 있어서 memcpy를 사용하면 안되는 상황인데
운이좋게 memcpy 의 구현사항에 따라 문제가 발생하지 않은 것 뿐이지요.

메모리 공간이 겹치는 경우는 memmove 를 사용하면 됩니다.
memmove 는 공간의 겹칩 여부를 확인해서 어떻게 겹쳐냐에 따라 앞에서 부터 뒤로, 혹은 뒤에서 부터 앞으로 복사할지
여부를 판단해서 작동하도록 되어 있습니다.
그래서 그 판단하는 과정 만큼의 오버헤드가 있지만, 복사할 메모리양이 3~4 바이트 정도로 작은게 아니라면
memcpy 와 memmove 의 수행속도는 거의 차이가 없다고 볼 수 있습니다.

실험적으로는 memmove 가 memcpy 보다 빠른 경우도 있지만, 아마 다른 요소에 의한 오차가 아닐까 합니다.
이론적으론 memcpy 가 빠릅니다. ^-^

kknd345의 이미지

답변 감사드립니다.

그런데 실무에서 memcpy 와 memmove 의 활용도가 높나요?

아직 학생인지라 for 문 돌려서 레코드 옮기는게 더 익숙해서요;;;

좋은 하루되세요 ^^

1%의 가능성이면 충분하다!
최선을 다하자!

kslee80의 이미지

for 루프 같은것으로 처리하는 것과,
memcpy 계열 함수로 처리하는 것의 속도차이는 꽤 심합니다.

몇백번의 루프를 돌아야 하는 정도라면 눈에 띄는 속도차는 없지만,
그 이상이거나, 아니면 루프 도는 횟수 자체는 적더라도 자주 돌아야 한다면
꽤 느껴질 정도로 납니다.

ohhara의 이미지

performance가 매우 중요한 상황이라면 src와 dst의 memory를 64bit나 128bit align으로 맞춰 주고 move를 assembly로 해당 platform에 맞춰서 해 주는 것이 좋습니다. ( IA32의 경우에는 MMX instruction 등을 사용 ) 그리고 src는 prefetch를 해서 cache에 미리 올려 놓고 dst는 cache를 건드리지 않고 직접 dram에 write하도록 해서 불피요한 cache fill이 일어나는 것을 피해주는 것이 좋습니다.

그 외의 경우에는 다른 분들 말 처럼 =나 memcpy, memmove를 사용하는 것이 좋습니다. 용도에 맞게 잘 선택하는 것이 중요합니다. ^^

Taeho Oh ( ohhara@postech.edu, ohhara@plus.or.kr ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
PLUS ( Postech Laboratory for Unix Security ) http://www.plus.or.kr

Taeho Oh ( ohhara@postech.edu ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Alticast Corp. http://www.alticast.com

ssehoony의 이미지

cache에 기록하지 않고 바로 dram 에 기록하도록 하는 인스트럭션도 있나요?

prefetch를 memcpy/memmove등에 활용하는 것은 꽤 좋은 아이디어군요.

하지만, 램에 직접 쓰는 인스트럭션이 있다고 하더라도 오히려 속도를 떨어뜨리는 일이 될 듯 한데요.
dram에 하나씩 하나씩 직접 쓰는 것 보다 cache에 쓰고, 후에 write-back으로 메모리에 한꺼번에 기록하는 쪽이 더 빠른거 아닌가요?
게다가 직접 ram에 기록하면 해당 페이지를 캐슁한 데이터는 invalid 될거고, 데이터를 복사했다는 것은 복사한 데이터를 어딘가에 이용하기 위함 일테고, 그럼 다시 메모리에서 캐쉬로 읽는 작업이 발생할텐데요.

익명사용자의 이미지

도대체 이런 정보들은 어디서 참고 하셔서 알고 계신겁니까?

좋은 책이나 자료있으면 알려주세요... 저도 좀 공부좀 하고 싶네요.

요즘 볼 책이 없는데 좋은 책 추천바랍니다.(뜬금없이 책추천-_-;;;)

ssehoony의 이미지

C++ 에서는 for 를 이용해 복사 연사자인 "=" 를 이용해 루프 돌며 복사하는 것이 좋다라고 보통 이야기 합니다. 구조체나 클래스의 복사에는 deep copy 와 shallow copy 라는 두개의 개념으로 나누는데, 가끔 deep copy 가 논리적으로 맞는 곳에서 memcpy 등을 이용해 shallow copy를 해버리는 경우가 있습니다. 이를 방지하기 위해 C++ 에서는 "=" 를 이용한 for 루프 복사를 해라 라고 합니다. C에서는 구조체 복사에서 이에 관련된 문제가 발생하지요.

가독성면에서 본다면 memcpy/memmove 가 참 좋습니다. 만약 for 루프로 되어 있으면 일단 for 문을 찬찬히 들여다 봐야 뭐하는 루프인지 알 수 있습니다. (주석은 없다고 생각했을 경우) 하지만, memcpy/memmove 를 사용했다면 바로 이해 할 수 있어서 가독성이 좋습니다. 마치 우리가 다른사람에게 뭔가 설명할때 전문용어를 이용하면 길게 풀어 설명해야할 것을 용어 하나로 편하게 나타낼 수 있는 것과 같죠. 이때는 듣는 사람도 그 전문용어는 충분히 이해하고 있어야한다는 전제가 따른다는 제약있습니다.

ohhara의 이미지

옛날 기억이라 가물가물해서 다시 web에서 search를 해 봤습니다. ^^;

http://mail-index.netbsd.org/tech-perform/2002/10/16/0000.html

cpu마다 다른 이야기이지만 일단 IA32를 기준으로 살펴보면 movntq라는 cache를 거치지 않고 직접 메모리에 write하는 뵨태(!) instruction이 존재합니다. 그리고 prefetch를 data에 대고 수동으로 때리는 prefetchnta라는 놈도 존재합니다.

그리고 data를 대량으로 메모리안에서 복사할 때는 movntq를 사용하는 방법이 cache를 사용하는 것보다 더 빠르다고 합니다. 당연히 소량으로 복사할 때 movntq를 사용하면 말씀하신 대로 다시 메모리에서 cache로 읽어야 되니까 시간이 더 오래 걸리겠지만 대량일 경우에는 cache miss가 연속적으로 일어날 것이 뻔히 예상되기 때문에 메모리에 직접 write하는 것이 빠른 듯(?) 합니다. 그리고 아마 이거는 제 추측인데 write-back으로 메모리에 한꺼번에 기록하는 것이 메모리에 직접 write하는 것보다 빠를 수도 있겠지만 write-back을 하기에 앞서 메모리의 내용을 cache로 가져오는 작업도 있기 때문에 상쇄되지 않나 생각됩니다.

Taeho Oh ( ohhara@postech.edu, ohhara@plus.or.kr ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
PLUS ( Postech Laboratory for Unix Security ) http://www.plus.or.kr

Taeho Oh ( ohhara@postech.edu ) http://ohhara.sarang.net
Postech ( Pohang University of Science and Technology ) http://www.postech.edu
Alticast Corp. http://www.alticast.com

ssehoony의 이미지

좋은 자료 감사합니다.
올려주신 주소에 있는 내용도 멋지네요.

ikpil의 이미지

웹에서 찾았으려 했을 때의 그 기본 지식은 무엇을 통해서 알게 되었는지 알고 싶습니다.
무엇인가 하려고 할때, 꼭 한번쯤 막히는 부분이 있는데, 여기에 분명 큰 도움이 될 것 같습니다.

cppig1995의 이미지

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.