memcmp,但需要将块与固定值进行比较 [英] memcmp but need to compare block with fixed value

查看:159
本文介绍了memcmp,但需要将块与固定值进行比较的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将内存块与C中的固定值进行比较.我可以使用memcmp做到这一点吗?像这样:

I need to compare a block of memory to a fixed value in C. Can I do this with memcmp? Something like:

memcmp(起始地址,固定值,数字字节)

memcmp (starting_address , fixed_value , num_byte)

我需要fixed_value为固定值,而不是块的起始地址.

I need fixed_value to be a fixed value not the starting address of a block.

  1. 将固定值写入整个临时存储块不是一种选择,因为我的空间有限.
  2. 使用循环逐个写入和检查内存不是一种选择,因为它非常慢.

如果不可能,谁能告诉我一个比memcmp更快(或更快)的解决方案?

If it's not possible can anyone tell me a solution that is as fast (or faster) than memcmp?

谢谢

假设我有5GB的内存,可容纳0.而且我正在尝试确保它们全为0.检查该块的第一个字节是否安全,然后执行以下操作:

Let's say I have 5GB of memory that holds 0's. And I'm trying to make sure they're all 0's. Is it safe to check the first byte of the block then do this:

memcmp(起始地址,起始地址+ ONE_BYTE,FIVE_GB); ?

memcmp (starting_address , starting_address + ONE_BYTE , FIVE_GB); ?

这就是为什么我需要使用memcmp而不是用户定义的循环的原因:

This is why I need to use memcmp and not a user defined loop:

此代码需要546个时钟滴答来运行:

This code took 546 clock ticks to run:

memset(0x80000000 , 0x1 , 0x10000000);
memset(0x90000000 , 0x1 , 0x10000000);
memcmp(0x80000000 , 0x90000000 , 0x10000000);

与花费了7669个时钟滴答声的时钟相比:

vs this one that took 7669 clock ticks:

unsigned int i;
int flag = 0;
int *p = 0x80000000;
int *q = 0x90000000;
while(p < 0x90000000)
{
    if(*p++ != *q++)
    {
        flag = 1;
    }
}

推荐答案

我刚刚在Mac上测试了此循环,它击败了memcmp:

I just tested this loop on my Mac, and it beats memcmp:

uint64_t *p = (uint64_t *)buffer1;
uint64_t compare;
memset(&compare, 1, sizeof compare);
for (i = 0; i < length/sizeof compare; i++)
{
    if (p[i] != compare)
        break;
}

完整的示例代码:

#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <time.h>
#include <stdlib.h>
#include <stdint.h>

// from: http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html
void timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
{
    /* Perform the carry for the later subtraction by updating y. */
    if (x->tv_usec < y->tv_usec)
    {
        int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
        y->tv_usec -= 1000000 * nsec;
        y->tv_sec += nsec;
    }

    if (x->tv_usec - y->tv_usec > 1000000)
    {
        int nsec = (x->tv_usec - y->tv_usec) / 1000000;
        y->tv_usec += 1000000 * nsec;
        y->tv_sec -= nsec;
    }

    /* Compute the time remaining to wait. tv_usec is certainly positive. */
    result->tv_sec = x->tv_sec - y->tv_sec;
    result->tv_usec = x->tv_usec - y->tv_usec;
}

int main(int argc, char **argv)
{
    struct rusage before;
    struct rusage after;
    struct timeval diff;
    size_t i;

    size_t length = strtoull(argv[1], NULL, 0);

    char *buffer1 = malloc(length);
    char *buffer2 = malloc(length);

    printf("filling...");
    fflush(stdout);
    memset(buffer1, 1, length);
    memset(buffer2, 1, length);
    printf(" done\n");

    getrusage(RUSAGE_SELF, &before);
    uint64_t *p = (uint64_t *)buffer1;
    uint64_t compare;
    memset(&compare, 1, sizeof compare);
    for (i = 0; i < length/sizeof compare; i++)
    {
        if (p[i] != compare)
            break;
    }
    if (i == length/sizeof compare)
        i = 0;
    getrusage(RUSAGE_SELF, &after);

    printf("\nloop (returned %zu):\n", i);
    timeval_subtract(&diff, &after.ru_utime, &before.ru_utime);
    printf("User:   %ld.%06d s\n", diff.tv_sec, diff.tv_usec);

    timeval_subtract(&diff, &after.ru_stime, &before.ru_stime);
    printf("System: %ld.%06d s\n", diff.tv_sec, diff.tv_usec);

    getrusage(RUSAGE_SELF, &before);
    i = memcmp(buffer1, buffer2, length);
    getrusage(RUSAGE_SELF, &after);

    printf("\nmemcmp (returned %zu):\n", i);
    timeval_subtract(&diff, &after.ru_utime, &before.ru_utime);
    printf("User:   %ld.%06d s\n", diff.tv_sec, diff.tv_usec);

    timeval_subtract(&diff, &after.ru_stime, &before.ru_stime);
    printf("System: %ld.%06d s\n", diff.tv_sec, diff.tv_usec);

    return 0;
}

运行结果:

$ make
clang -Wall -Wextra -Werror -O3 -g -o example example.c
./example 0x10000000
filling... done

loop (returned 0):
User:   0.024078 s
System: 0.000011 s

memcmp (returned 0):
User:   0.036752 s
System: 0.000017 s

也许您可以做类似的事情?

Maybe you can do something similar?

注意:对于那些关心高速缓存预热的人,我还在循环前尝试了memcmp并获得了相同的结果.

Note: For those concerned about cache warming, I also tried with the memcmp before the loop and got the same results.

这篇关于memcmp,但需要将块与固定值进行比较的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆