char보다 큰 정수를 받아들이는 memset()이 있습니까?
1바이트(char)보다 큰 값을 설정하는 memset() 버전이 있습니까?예를 들어, memset32() 함수가 있다고 가정해 보겠습니다. 따라서 이 함수를 사용하면 다음과 같은 작업을 수행할 수 있습니다.
int32_t array[10];
memset32(array, 0xDEADBEEF, sizeof(array));
0xDEADB 값을 설정합니다.배열의 모든 요소에 EEF가 있습니다.현재 제가 보기에 이것은 루프로만 이루어질 수 있습니다.
특히 64비트 버전의 memset()에 관심이 있습니다.그런 거 아세요?
void memset64( void * dest, uint64_t value, uintptr_t size )
{
uintptr_t i;
for( i = 0; i < (size & (~7)); i+=8 )
{
memcpy( ((char*)dest) + i, &value, 8 );
}
for( ; i < size; i++ )
{
((char*)dest)[i] = ((char*)&value)[i&7];
}
}
(설명: 설명은 주석에서 요청한 대로: 포인터를 할당할 때 컴파일러는 포인터가 유형의 자연 정렬에 맞춰진 것으로 가정합니다. uint64_t의 경우 8바이트입니다.memcpy ()는 그러한 가정을 하지 않습니다.일부 하드웨어에서는 정렬되지 않은 액세스가 불가능하므로 하드웨어에서 정렬되지 않은 액세스가 작동한다는 것을 알거나 패널티가 크지 않거나 발생하지 않는다는 것을 알거나 둘 다 알지 않는 한 할당은 적합한 솔루션이 아닙니다.컴파일러는 작은 memcpy()와 memset()을 더 적합한 코드로 교체하므로 보기만큼 끔찍하지는 않습니다. 그러나 할당이 항상 작동할 것이라는 것을 충분히 알고 있고 프로파일러가 더 빠르다고 알려준다면 할당으로 memcpy를 교체할 수 있습니다.채워질 메모리의 양이 64비트의 배수가 아닌 경우에는 두 번째 for() 루프가 존재합니다.항상 그럴 것이라는 것을 알고 있다면, 그 루프를 중단하면 됩니다.)
표준 라이브러리 기능이 없습니다.휴대용 코드를 쓰고 있다면 루프를 보고 있는 것입니다.
휴대용이 아닌 코드를 작성하는 경우 컴파일러/플랫폼 설명서를 확인하십시오. 하지만 여기서 많은 도움을 받는 경우는 드물기 때문에 숨을 쉬지 마십시오.아마도 다른 누군가가 무언가를 제공하는 플랫폼의 예를 들어줄 것입니다.
호출자가 플랫폼(또는 휴대용인 경우 플랫폼)의 64비트 쓰기를 위해 dst 포인터가 충분히 정렬됨을 보장한다는 것을 API에 정의할 수 있는지 여부에 따라 자신의 쓰기 방식이 달라집니다.64비트 정수 타입이 있는 플랫폼에서 malloc는 적어도 적절하게 정렬된 포인터를 반환할 것입니다.
만약 당신이 비정렬에 대처해야 한다면, 당신은 moonshadow의 답변과 같은 것이 필요합니다.컴파일러는 크기가 8인 memcpy를 인라인/언롤할 수 있으므로 코드가 꽤 약할 수 있지만, 정렬되는 대상에 대한 전체 함수를 특수하게 사용하지는 않을 것입니다.저는 교정을 받고 싶지만, 그러지 못할까 봐 두려워요.
따라서 호출자가 아키텍처에 맞는 충분한 정렬과 8바이트의 배수인 길이를 항상 제공한다는 것을 알고 있다면 uint64_t(또는 컴파일러에 있는 64비트 int가 무엇이든)를 작성하는 간단한 루프를 수행하면 아마도 더 빠른 코드가 나올 것입니다.분명히 코드가 짧아질 겁니다.
어떤 경우든 성능에 신경 쓴다면 프로파일링을 하세요.속도가 너무 빠르지 않으면 최적화 작업을 다시 시도합니다.그래도 속도가 충분하지 않은 경우 CPU의 ASM 버전에 대해 질문하십시오. memcpy/memset은 플랫폼별 최적화를 통해 성능이 크게 향상될 수 있습니다.
단지 기록을 위해 다음과 같은 용도가 있습니다.memcpy(..)다음과 같은 양상으로배열을 20개의 정수로 채우려고 합니다.
--------------------
First copy one:
N-------------------
Then copy it to the neighbour:
NN------------------
Then copy them to make four:
NNNN----------------
And so on:
NNNNNNNN------------
NNNNNNNNNNNNNNNN----
Then copy enough to fill the array:
NNNNNNNNNNNNNNNNNNNN
이것은 O(lg(num))의 응용 프로그램을 사용합니다.memcpy(..).
int *memset_int(int *ptr, int value, size_t num) {
if (num < 1) return ptr;
memcpy(ptr, &value, sizeof(int));
size_t start = 1, step = 1;
for ( ; start + step <= num; start += step, step *= 2)
memcpy(ptr + start, ptr, sizeof(int) * step);
if (start < num)
memcpy(ptr + start, ptr, sizeof(int) * (num - start));
return ptr;
}
루프보다 더 빠를 수도 있다고 생각했어요.memcpy(..)일부 하드웨어 블록 메모리 복사 기능을 사용하여 최적화되었지만 -O2 및 -O3의 경우 단순 루프가 위보다 더 빠르다는 것이 밝혀졌습니다. (적어도 윈도우에서 특정 하드웨어와 함께 MinGW GCC를 사용합니다.)-O 스위치가 없으면 400MB 어레이에서 위의 코드는 등가 루프보다 약 2배 빠르며, 내 기계에서는 417ms가 소요되며, 최적화를 통해 둘 다 약 300ms가 됩니다.즉, 바이트와 거의 동일한 수의 나노초가 소요되며, 클럭 주기는 약 1나노초입니다.그래서 내 기계에 하드웨어 블록 메모리 복사 기능이 없거나,memcpy(..)구현은 이를 활용하지 않습니다.
OS 설명서에서 로컬 버전을 확인한 다음 루프를 사용하는 것을 고려합니다.
컴파일러는 특정 아키텍처에서 메모리 액세스를 최적화하는 방법을 사용자보다 더 잘 알고 있을 것입니다.
라이브러리로 포장하고 컴파일러가 허용하는 모든 속도 향상 최적화와 함께 컴파일합니다.
wmemset(3)는 넓은(16비트) 버전의 멤셋입니다.루프 없이 C에 들어갈 수 있는 가장 가까운 거리라고 생각합니다.
x86 컴파일러를 대상으로 한다면 다음과 같은 것을 시도해 볼 수 있습니다(VC++ 예제).
inline void memset32(void *buf, uint32_t n, int32_t c)
{
__asm {
mov ecx, n
mov eax, c
mov edi, buf
rep stosd
}
}
그렇지 않으면 간단한 루프를 만들고 옵티마이저가 무엇을 하고 있는지 알 수 있도록 신뢰하면 됩니다. 다음과 같은 것이 있습니다.
for(uint32_t i = 0;i < n;i++)
{
((int_32 *)buf)[i] = c;
}
복잡한 가능성을 만들면 코드를 최적화하는 것이 단순한 것보다 느릴 뿐만 아니라 유지보수도 더 어려워집니다.
다른 사람이 제안한 대로 컴파일러가 이를 최적화하도록 해야 합니다.대부분의 경우 루프는 무시할 수 있습니다.
하지만 이것이 특별한 상황이고 플랫폼에 특정한 것에 개의치 않고 정말로 루프를 제거해야 한다면 조립 블록에서 이 작업을 수행할 수 있습니다.
//pseudo code
asm
{
rep stosq ...
}
자세한 내용은 아마 구글 stosq assembly 명령어를 사용할 수 있을 것입니다.코드가 몇 줄 이상이면 안 됩니다.
언급URL : https://stackoverflow.com/questions/108866/is-there-memset-that-accepts-integers-larger-than-char
'programing' 카테고리의 다른 글
| PL/SQL 전용 VARCHAR232767 바이트를 모두 만들지 않는 이유는 무엇입니까? (0) | 2023.10.30 |
|---|---|
| C/C++ 서로 다른 플랫폼에서 동적 연결은 어떻게 작동합니까? (0) | 2023.10.30 |
| AngularJS에서 배열이 아닌 개체 맵에서 필터링 (0) | 2023.10.25 |
| $.param을 angularjs로 변환 (0) | 2023.10.25 |
| WooCommerce 백엔드와 같이 각 카테고리의 상품 수를 얻으려면 어떻게 해야 합니까? (0) | 2023.10.25 |