击败或满足 OS X memset(和 memset_pattern4)

2023-12-23

我的问题是基于另一个SO问题:为什么 _mm_stream_ps 会产生 L1/LL 缓存未命中? https://stackoverflow.com/questions/9068246/why-does-mm-stream-ps-produce-l1-ll-cache-misses

阅读完它并对其感兴趣后,我尝试复制结果并亲自看看哪个更快:朴素循环,展开朴素循环,_mm_stream_ps(展开),_mm_store_ps(展开)最后但并非最不重要的memset_pattern4。 (最后一个函数采用 4 字节模式,例如浮点数,并将其粘贴到整个目标数组上,这应该与所有其他函数执行相同的操作,但它可能是 OS X 独有的)。

我已确保将数组的开头对齐到缓存行(64 字节,我检查过),并在参数中传递数组以及上一个问题中提到的任何其他性能调整。

其他人想在 gamedev 上了解同样的事情:http://www.gamedev.net/topic/532112-fast-memset/ http://www.gamedev.net/topic/532112-fast-memset/

该线程的结论反映了我自己的结论:当目标数组小于最大(L3)缓存时,_mm_store_ps_mm_stream_ps。当目标数组较大时,_mm_stream_ps是比较快的。我不太确定为什么__mm_store_ps在第一种情况下更快,因为我从不在缓存中使用这些值,但我明白为什么_mm_stream_ps在后一种情况下胜出。它是针对这种情况而设计的:将字节写入您不会立即(或永远)不需要的内存。

以下是使用 gcc 4.8 编译的目标数组比 L3 缓存大 256 倍(在我的例子中为 1.5GB)的一些结果:

gcc-4.8 stream.c -o stream -std=c11 -O3 -g3 -ftree-vectorize -march=native -minline-all-stringops && ./stream

bench L3-MASS, array 1610612736 bytes (402653184 floats, 0 remainder, 0x104803040 pointer)
warm up round...
      6% (  20.81148 ms) : MEMSET CHEAT
      8% (  28.49419 ms) : MEMSET PATTER
    100% ( 371.40385 ms) : NAIVE  NORMAL
     54% ( 202.01147 ms) : NAIVE  UNROLL
     31% ( 113.53433 ms) : STREAM NORMAL
     30% ( 111.41691 ms) : STREAM UNROLL
     51% ( 190.70412 ms) : STORE  NORMAL
     51% ( 189.15338 ms) : STORE  UNROLL
     51% ( 189.36182 ms) : STORE  PREFET

那么我们从中学到什么呢?memset_pattern4快得令人难以置信。我包括沼泽标准memset即使它只使用 1 字节模式进行比较。在本质上,memset作弊,但是memset_pattern4不,而且速度仍然很快。

我尝试查看程序集以查找我认为是源代码的内容memset_pattern4在 OS X 字符串库中:

  • 苹果的libc,memset_pattern4: http://www.opensource.apple.com/source/Libc/Libc-825.25/string/memset_pattern.c?txt http://www.opensource.apple.com/source/Libc/Libc-825.25/string/memset_pattern.c?txt
  • 这引用了所谓的 bcopy 函数。让我们来挖掘一下: 字符串库:http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/ http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/
  • 我的情况很可能使用的是 SSE 4.2 版本:http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/bcopy_sse42.s http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/bcopy_sse42.s

我对 asm 的了解(到目前为止)已经足够多了,我看到他们正在使用movdqa重要的指示(在LAlignedLoop部分),这基本上是整数(不是浮点数)的 SSE 移动指令,内在:_mm_store_si128。位和字节在这里并不重要,对吧?

  • 似乎还有一个纯 asm 实现memset_pattern4,这看起来不同,因为它没有调用bcopy: http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/memset.s http://www.opensource.apple.com/source/Libc/Libc-763.13/x86_64/string/memset.s (EDIT:这是正确的,通过在 gdb 下运行验证)

...该死的,这个似乎使用非时间(_mm_stream_ps存储很长的数组=>movntdq %xmm0,(%rdi,%rcx)...,查看LVeryLong函数的部分),这正是我所做的!那么怎样才能更快呢?也许这不是memset_pattern4我在找。

那么,什么是memset_pattern4为什么它比我的最佳尝试快 5 倍?尽管我一直在努力学习足够的 x86 汇编以便能够剖析该函数,但我担心目前调试优化至死函数中的性能问题有点超出我的能力。

NOTE:对于那些好奇的人来说,这个微基准还可以说明 clang 及其高级矢量化的绝对强大之处(-fslp-vectorize),它设法使朴素循环成为几乎在所有情况下保存 memset 最快的循环。它似乎与最佳组合一样好_mm_store_ps and _mm_stream_ps.

CODE:这是我用来执行基准测试的代码(要点:https://gist.github.com/6571379 https://gist.github.com/6571379):

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>

/**
 * compile and run:
 *
 * OSX:
 *    clang stream.c -o stream -std=c11 -O3 -g -ftree-vectorize -fslp-vectorize -march=native -minline-all-stringops && ./stream
 *    gcc-4.8 stream.c -o stream -std=c11 -O3 -g3 -ftree-vectorize -march=native -minline-all-stringops && ./stream
 *
 * linux:
 *    clang stream.c -o stream -lrt -std=c11 -O3 -ftree-vectorize -fslp-vectorize -march=native && ./stream
 *    gcc-4.8 stream.c -o stream -lrt -std=c11 -O3 -ftree-vectorize -march=native && ./stream
 *
 * to generate the assembly:
 *    gcc-4.8 -S stream.c -o stream.s -std=c11 -O3 -g3 -ftree-vectorize -march=native -minline-all-stringops
 *    gobjdump -dS stream > stream.obj.s
 *
 * clang is the (very clear) winner here, the SLP vectorizer is absolutely killer, it even turns the
 * plain naive loop into something hyper-performant
 */

/* posix headers */
#include <sys/time.h>

/* intrinsics */
#include <x86intrin.h>

#define ARRAY_SIZE(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))


/**
 * some stats from my system
 *
 * sudo sysctl -a | grep cache
 *
 * hw.cachelinesize = 64
 * hw.l1icachesize = 32768
 * hw.l1dcachesize = 32768
 * hw.l2cachesize = 262144
 * hw.l3cachesize = 6291456
 */

/* most processors these days (2013) have a 64 byte cache line */
#define FACTOR          1024
#define CACHE_LINE      64
#define FLOATS_PER_LINE (CACHE_LINE / sizeof(float))
#define L1_CACHE_BYTES  32768
#define L2_CACHE_BYTES  262144
#define L3_CACHE_BYTES  6291456


#ifdef __MACH__
#include <mach/mach_time.h>

double ns_conversion_factor;
double us_conversion_factor;
double ms_conversion_factor;

void timeinit() {
    mach_timebase_info_data_t timebase;
    mach_timebase_info(&timebase);

    ns_conversion_factor = (double)timebase.numer / (double)timebase.denom;
    us_conversion_factor = (double)timebase.numer / (double)timebase.denom / 1000;
    ms_conversion_factor = (double)timebase.numer / (double)timebase.denom / 1000000;
}

double nsticks() {
    return mach_absolute_time() * ns_conversion_factor;
}

double msticks() {
    return mach_absolute_time() * ms_conversion_factor;
}

#else

void timeinit() {
    /* do nothing */
}

double nsticks() {
    timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);

    return ((double)ts.tv_sec) / 1000000000 + ((double)ts.tv_nsec);
}

double msticks() {
    timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);

    return ((double)ts.tv_sec) / 1000 + ((double)ts.tv_nsec) * 1000000;
}

#endif


void *aligned_malloc(size_t size, size_t alignment) {
    void *pa, *ptr;

    pa = malloc((size+alignment-1)+sizeof(void *));
    if (!pa) return NULL;

    ptr=(void*)( ((intptr_t)pa+sizeof(void *)+alignment-1)&~(alignment-1) );
    *((void **)ptr-1)=pa;

    return ptr;
}

void aligned_free(void *ptr) {
    if (ptr) free(*((void **)ptr-1));
}

void pollute_cache(uint8_t volatile *arr, size_t length) {
    for (int i = 0; i < length; ++i) {
        arr[i] = (arr[i] > 0xFE) ? 0xAA : 0x55;
    }
}

void pollute_cache_standalone() {
    const size_t pollute_len = 2 * L3_CACHE_BYTES;
    uint8_t *arr             = aligned_malloc(pollute_len * sizeof(uint8_t), 64);

    for (int i = 0; i < pollute_len; ++i) {
        arr[i] = (arr[i] > 0xFE) ? 0xAA : 0x55;
    }

    aligned_free(arr);
}

/**
 * returns the time passed, in milliseconds
 */
double tim(const char *name, double baseline, void (*pre)(void), void (*func)(float *, size_t), float * restrict arr, size_t length) {
    struct timeval t1, t2;

    if (pre) pre();

    const double ms1 = msticks();
    func(arr, length);
    const double ms2 = msticks();

    const double ms = (ms2 - ms1);

    if (baseline == -2.0) return ms;

    /* first run, equal to baseline (itself) by definition */
    if (baseline == -1.0) baseline = ms;

    if (baseline != 0.0) {
        fprintf(stderr, "%7.0f%% (%10.5f ms) : %s\n", (ms / baseline) * 100, ms, name);
    }
    else {
        fprintf(stderr, "%7.3f ms : %s\n", ms, name);
    }

    return ms;
}

void func0(float * const restrict arr, size_t length) {
    memset(arr, 0x05, length);
}

#ifdef __MACH__

void funcB(float * const restrict arr, size_t length) {
    const float val = 5.0f;
    memset_pattern4(arr, &val,length);
}

#endif

void func1(float * const restrict arr, size_t length) {
    for (int i = 0; i < length; ++i) {
        arr[i] = 5.0f;
    }
}

void func2(float * const restrict arr, size_t length) {
    for(int i = 0; i < length; i += 4) {
        arr[i]   = 5.0f;
        arr[i+1] = 5.0f;
        arr[i+2] = 5.0f;
        arr[i+3] = 5.0f;
    }
}

void func3(float * const restrict arr, size_t length) {
    const __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 4) {
        _mm_stream_ps(&arr[i], buf);
    }

    _mm_mfence();
}

void func4(float * const restrict arr, size_t length) {
    const __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 16) {
        _mm_stream_ps(&arr[i + 0], buf);
        _mm_stream_ps(&arr[i + 4], buf);
        _mm_stream_ps(&arr[i + 8], buf);
        _mm_stream_ps(&arr[i + 12], buf);
    }

    _mm_mfence();
}

void func5(float * const restrict arr, size_t length) {
    const __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 4) {
        _mm_store_ps(&arr[i], buf);
    }
}

void fstore_prefetch(float * const restrict arr, size_t length) {
    const __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 16) {
        __builtin_prefetch(&arr[i + FLOATS_PER_LINE * 32], 1, 0);
        _mm_store_ps(&arr[i + 0], buf);
        _mm_store_ps(&arr[i + 4], buf);
        _mm_store_ps(&arr[i + 8], buf);
        _mm_store_ps(&arr[i + 12], buf);
    }
}

void func6(float * const restrict arr, size_t length) {
    const __m128 buf = _mm_setr_ps(5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 16) {
        _mm_store_ps(&arr[i + 0], buf);
        _mm_store_ps(&arr[i + 4], buf);
        _mm_store_ps(&arr[i + 8], buf);
        _mm_store_ps(&arr[i + 12], buf);
    }
}

#ifdef __AVX__

void func7(float * restrict arr, size_t length) {
    const __m256 buf = _mm256_setr_ps(5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 8) {
        _mm256_stream_ps(&arr[i], buf);
    }
}

void func8(float * restrict arr, size_t length) {
    const __m256 buf = _mm256_setr_ps(5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 32) {
        _mm256_stream_ps(&arr[i + 0], buf);
        _mm256_stream_ps(&arr[i + 8], buf);
        _mm256_stream_ps(&arr[i + 16], buf);
        _mm256_stream_ps(&arr[i + 24], buf);
    }
}

void func9(float * restrict arr, size_t length) {
    const __m256 buf = _mm256_setr_ps(5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 8) {
        _mm256_store_ps(&arr[i], buf);
    }
}

void funcA(float * restrict arr, size_t length) {
    const __m256 buf = _mm256_setr_ps(5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f, 5.0f);

    for (int i = 0; i < length; i += 32) {
        _mm256_store_ps(&arr[i + 0], buf);
        _mm256_store_ps(&arr[i + 8], buf);
        _mm256_store_ps(&arr[i + 16], buf);
        _mm256_store_ps(&arr[i + 24], buf);
    }
}

#endif

void bench(const char * restrict name, float * restrict arr, size_t length) {
    fprintf(stderr, "bench %s, array %zu bytes (%zu floats, %zu remainder, %p pointer)\n", name, length, length / sizeof(float), length % sizeof(float), arr);

    size_t nfloats = length / sizeof(float);

    fprintf(stderr, "warm up round...");
    func1(arr, nfloats);
    fprintf(stderr, "done\n");

    double baseline = tim("func1: NAIVE ", -2.0, NULL, func1, arr, nfloats);

    tim("MEMSET CHEAT ", baseline, NULL, func0, arr, nfloats);
#ifdef __MACH__
    tim("MEMSET PATTER", baseline, NULL, funcB, arr, nfloats);
#endif
    tim("NAIVE  NORMAL", -1.0, NULL, func1, arr, nfloats);
    tim("NAIVE  UNROLL", baseline, NULL, func2, arr, nfloats);
    tim("STREAM NORMAL", baseline, NULL, func3, arr, nfloats);
    tim("STREAM UNROLL", baseline, NULL, func4, arr, nfloats);
    tim("STORE  NORMAL", baseline, NULL, func5, arr, nfloats);
    tim("STORE  UNROLL", baseline, NULL, func6, arr, nfloats);
    tim("STORE  PREFET", baseline, NULL, fstore_prefetch, arr, nfloats);

    // for (int i = 0; i < 1; ++i) {
    //     tim("func0: MEMSET (cache polluted)", NULL, func0, arr, nfloats);
    //     tim("func1: NAIVE  (cache polluted)", pollute_cache_standalone, func1, arr, nfloats);
    //     tim("func2: UNROLL (cache polluted)", pollute_cache_standalone, func2, arr, nfloats);
    //     tim("func3: STREAM (cache polluted)", pollute_cache_standalone, func3, arr, nfloats);
    //     tim("func4: STRUN  (cache polluted)", pollute_cache_standalone, func4, arr, nfloats);
    //     tim("func5: STORE  (cache polluted)", pollute_cache_standalone, func5, arr, nfloats);
    //     tim("func6: STOUN  (cache polluted)", pollute_cache_standalone, func6, arr, nfloats);
    // }
}

int main() {
    timeinit();

    static const struct {
        const char *name;
        size_t bytes;
    } sizes[] = {
        { "L1-HALF", L1_CACHE_BYTES / 2 },
        { "L1-FULL", L1_CACHE_BYTES },
        { "L2-HALF", L2_CACHE_BYTES / 2 },
        { "L2-FULL", L2_CACHE_BYTES },
        { "L3-HALF", L3_CACHE_BYTES / 2 },
        { "L3-FULL", L3_CACHE_BYTES },
        { "L3-DOUB", L3_CACHE_BYTES * 2 },
        { "L3-HUGE", L3_CACHE_BYTES * 64 },
        { "L3-MASS", L3_CACHE_BYTES * 256 }
    };

    for (int i = 0; i < ARRAY_SIZE(sizes); ++i) {
        size_t bytes = sizes[i].bytes;

        /* align to cache line */
        float *arr = aligned_malloc(bytes, CACHE_LINE);

        bench(sizes[i].name, arr, bytes);

        aligned_free(arr);
    }

    return 0;
}

EDIT:我进一步挖掘了一下,编辑了 gcc 生成的程序集,使其或多或少与苹果使用的程序集相同(memset.s, label LVeryLong,即:4 个展开movntdq紧密循环中的指令)。令我惊讶的是,我获得了与使用以下函数相同的性能_mm_store_ps (movaps)。这让我很困惑,因为我本来期望它是

  1. 跟...一样快memset_pattern4(大概是展开的movntdq)
  2. 与展开一样快_mm_stream_ps (movntdq)

但不,它似乎是一样的_mm_store_ps,想象一下,也许我做错了什么。在生成的二进制文件上运行 objdump 确认它正在使用movntdq,这更让我惊讶,这到底是怎么回事?

因为我在那里遇到了死胡同,所以我决定在调试器中单步执行可执行文件并在以下位置设置一个断点memset_pattern4。进入该函数后,我注意到它的功能与我的预期完全一致,是一个带有四个展开的紧密循环movntdq:

   0x00007fff92a5f7d2 <+318>:   jmp    0x7fff92a5f7e0 <memset_pattern4+332>
   0x00007fff92a5f7d4 <+320>:   nopw   0x0(%rax,%rax,1)
   0x00007fff92a5f7da <+326>:   nopw   0x0(%rax,%rax,1)
   0x00007fff92a5f7e0 <+332>:   movntdq %xmm0,(%rdi,%rcx,1)
   0x00007fff92a5f7e5 <+337>:   movntdq %xmm0,0x10(%rdi,%rcx,1)
   0x00007fff92a5f7eb <+343>:   movntdq %xmm0,0x20(%rdi,%rcx,1)
   0x00007fff92a5f7f1 <+349>:   movntdq %xmm0,0x30(%rdi,%rcx,1)
   0x00007fff92a5f7f7 <+355>:   add    $0x40,%rcx
=> 0x00007fff92a5f7fb <+359>:   jne    0x7fff92a5f7e0 <memset_pattern4+332>
   0x00007fff92a5f7fd <+361>:   sfence

那么,是什么让苹果酱比我的更神奇,我想知道......

EDIT 2:我在这里错了两次,Apple 的魔法酱并没有那么神奇,我只是传递了一个比我传递给函数的数组小 4 倍的数组。感谢@PaulR 的关注!其次,我正在编辑函数的汇编,但 gcc 已经内联了它。所以我正在编辑一个从未使用过的副本。

结论:

我发现的其他一些事情:

  • Clang 和 gcc 确实很好,有了正确的内在函数,它们就进行了很多优化(当启用 SLP 矢量器时,clang 甚至在没有内在函数的情况下也能做得很好)。他们还将内联函数指针。
  • Clang 会将一个简单的循环替换为一个常量memset打电话,澄清了我的另一个令人困惑的结果。
  • 非临时存储(即:流)仅对大量写入有益
  • memset确实优化得很好,它会根据要写入的数组的长度自动在常规存储和非临时存储(流)之间切换。我不确定这在 OSX 以外的平台上有多少是正确的
  • 在编写基准测试时,请绝对确保该函数按照您的想法进行操作,并且编译器不会比您更聪明。第一种情况是我的问题,我没有提供正确的参数。

EDIT: 最近偶然发现英特尔优化指南 http://www.intel.com/content/dam/doc/manual/64-ia-32-architectures-optimization-manual.pdf,如果对这些事情感兴趣,请先阅读其中的某些部分(也许从 3.7.6 开始)。


我认为你这里有几个错误:

void func0(float * const restrict arr, size_t length) {
    memset(arr, 0x05, length);
}

和这里类似:

void funcB(float * const restrict arr, size_t length) {
    const float val = 5.0f;
    memset_pattern4(arr, &val,length);
}

这些实际上应该是:

void func0(float * const restrict arr, size_t length) {
    memset(arr, 0x05, length * sizeof(float));
}

and:

void funcB(float * const restrict arr, size_t length) {
    const float val = 5.0f;
    memset_pattern4(arr, &val, length * sizeof(float));
}

这将给出比这两种情况应有的时间乐观 4 倍的时间。

在我用了 3 年的 Core i7 MacBook Pro(8 GB RAM)上,固定代码给了我:

bench L3-HUGE, array 402653184 bytes (100663296 floats, 0 remainder, 0x108ed8040 pointer)
warm up round...done
     99% (  69.43037 ms) : MEMSET CHEAT 
    106% (  73.98113 ms) : MEMSET PATTER
    100% (  72.40429 ms) : NAIVE  NORMAL
    120% (  83.98352 ms) : NAIVE  UNROLL
    102% (  71.75789 ms) : STREAM NORMAL
    102% (  71.59420 ms) : STREAM UNROLL
    115% (  80.63817 ms) : STORE  NORMAL
    123% (  86.58758 ms) : STORE  UNROLL
    123% (  86.22740 ms) : STORE  PREFET
bench L3-MASS, array 1610612736 bytes (402653184 floats, 0 remainder, 0x108ed8040 pointer)
warm up round...done
     83% ( 274.71955 ms) : MEMSET CHEAT 
     83% ( 275.19793 ms) : MEMSET PATTER
    100% ( 272.21942 ms) : NAIVE  NORMAL
     94% ( 309.73151 ms) : NAIVE  UNROLL
     82% ( 271.38751 ms) : STREAM NORMAL
     82% ( 270.27244 ms) : STREAM UNROLL
     94% ( 308.49498 ms) : STORE  NORMAL
     94% ( 308.72266 ms) : STORE  UNROLL
     95% ( 311.64157 ms) : STORE  PREFET
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

击败或满足 OS X memset(和 memset_pattern4) 的相关文章

  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 如何在没有 Control.Invoke() 的情况下从后台线程修改控件属性

    最近 我们遇到了一些旧版 WinForms 应用程序 我们需要更新一些新功能 在专家测试该应用程序时 发现一些旧功能被破坏 无效的跨线程操作 现在 在您认为我是新手之前 我确实有一些 Windows 窗体应用程序的经验 我不是专家 但我认为
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 如何在我的应用程序中使用 Windows Key

    Like Windows Key E Opens a new Explorer Window And Windows Key R Displays the Run command 如何在应用程序的 KeyDown 事件中使用 Windows
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c# Asp.NET MVC 使用FileStreamResult下载excel文件

    我需要构建一个方法 它将接收模型 从中构建excel 构建和接收部分完成没有问题 然后使用内存流导出 让用户下载它 不将其保存在服务器上 我是 ASP NET 和 MVC 的新手 所以我找到了指南并将其构建为教程项目 public File
  • 将代码保存在 L1 缓存中

    我一直在阅读维基百科关于 K 编程语言的文章 http en wikipedia org wiki K programming language Performance characteristics这就是我所看到的 解释器的小尺寸和语言的
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器

随机推荐

  • 创建 Hibernate SessionFactory 时如何设置数据源?

    我正在创建 SessionFactory 并且我将数据源作为我正在创建 SessionFactory 的代码中的对象 但我无法将数据源设置为 Hibernate Configuration 对象 那么如何将数据源设置为 SessionFac
  • ASP.NET core 2.2 Web api 记录与数据保护密钥相关的警告:我们应该如何处理这个问题?

    我们有一个 ASP NET core 2 2 Web 应用程序 公开了一些 Web API 控制器 我们的应用程序没有任何类型的身份验证机制 所有公开的端点都可以由匿名用户调用 当我们在 IIS 下托管应用程序时 我们在应用程序启动时收到三
  • 在 Web 应用程序开发环境中进行更新时要复制到生产服务器的内容

    我有一个在 Asp net Framework 3 5 Net 2008 中构建的 Web 应用程序 我使用 Web 部署项目 WDP 来编译它 我想知道 例如 如果我对代码隐藏文件 aspx vb 进行了一些更改 我需要将哪些文件上传到生
  • ArrayList 是否替换给定索引处存在的元素?

    如果给定索引处存在于 ArrayList 中 如何替换元素 arrayList set index i String replaceElement
  • 通常只允许每个套接字地址(协议/网络地址/端口)使用一次

    我正在连接到 Asp Net 中的 TCP IP 端口 基本上我已经在我正在读取的该端口上附加了一个设备 它工作正常 但第二次当 tcp 侦听器尝试启动时 它会生成上述错误 任何人都可以指导我如何摆脱这个错误这是我用来连接到 TCP IP
  • PHP #region 用于代码折叠?

    PHP 中是否有相当于 c 的 region 的功能 不 语言中没有直接的内容 但每一个像样的编辑器都允许某种标记来实现这一点 例如在 Netbeans 中
  • GKE 集群未缩小规模

    我在 Google Kubernetes 集群上启用了自动缩放 并且我可以看到其中一个 Pod 的使用率要低得多 我总共有 6 个节点 我预计至少有这个节点被终止 我经历了以下事情 https github com kubernetes a
  • Firebase、Android、Google Plus 登录 - 无法检索用户的电子邮件地址

    我正在使用 Google Plus 身份验证和 Firebase 我目前正在使用 Android 来完成基本的身份验证示例 基本身份验证部分与 github 上的代码运行良好 并且它应该按预期工作 https github com fire
  • 可见性:隐藏和显示:无之间有什么区别?

    CSS 规则visibility hidden and display none两者都会导致元素不可见 这些是同义词吗 display none意味着相关标签根本不会出现在页面上 尽管您仍然可以通过 dom 与其交互 其他标签之间不会为其分
  • Pandas 中日期列的最大/最小,列包含 nan 值

    我正在尝试在 pandas 数据框中创建一个新列 其中包含其他两个日期列的最大 或最小 日期 但是 当这两列中的任意位置存在 NAN 时 整个最小 最大列就会变成 NAN 是什么赋予了 当使用数字列时 这工作得很好 但是对于日期 新列都是
  • 有没有办法动态查询数据库

    我们想要为房间数据库构建一个过滤器 其中过滤器选项由用户选择 IE 我们有一个带有字段 id 名称 日期 类型 的实体 用户可以按日期和 或名称包含文本和 或类型等于某些内容来过滤列表 有没有办法在房间里做到这一点 我很遗憾地说 目前无法按
  • KSQL 流 - 从结构数组中获取数据

    我的 JSON 看起来像 Obj1 a abc b def c ghi ArrayObj key1 1 Key2 2 Key3 3 key1 4 Key2 5 Key3 6 key1 7 Key2 8 Key3 9 我已经编写了 KSQL
  • R Shiny DT 数据表排序/过滤时如何确保行着色更新?

    我正在编写一个 R Shiny 应用程序 我在 DT 数据表中使用具有特定颜色的文本条目 当表格重新排序时 颜色不会保留在正确的行中 相反 他们留在原地 我假设我需要观察表被重新排序 过滤的事件并做出反应 我怎么做 下面的示例代码 libr
  • 更改按钮颜色 onPress(切换功能)React Native

    希望一切安好 我似乎在使用基本按钮功能时遇到困难 我所需要的只是要更改的类的状态以及每次按下按钮时要更改的按钮样式 与 TouchableHighlight 不同 我需要更改颜色以保持直到再次按下按钮 返回到原始颜色 我尝试过使用 Swit
  • Play Framework 2.1.1 部署问题

    因此 我正在尝试部署非常简单的 Play Framework 2 1 1 应用程序 但每当我通过端口命令行传递标志并应用数据库演变时 它们都会被忽略 例如 sudo play start Dhttp port 80 DapplyEvolut
  • 如何在 Maven Netbeans 项目中包含 Maven 存储库中不存在的 jar

    我正在使用 Netbeans 构建 Maven 项目 并将 JTidy java 库作为依赖项 事实证明 JTidy 不存在于任何 Maven 存储库中 因此我不能只为其添加 正常 依赖项条目 处理 Maven 项目中库的依赖关系 在存储库
  • 为什么 type(classInstance) 返回“instance”?

    我有一个方法 它接受可以是多种类型的参数 并且必须根据类型做一件事或另一件事 但是如果我检查所述参数的类型 我不会得到 真实 类型 我总是得到
  • C# 中的标准 Blowfish

    我的 C 程序使用的是标准河豚 我的 C 程序使用的是 Blowfish 加密算法here http www hotpixel net software html 两个应用程序 TCP 客户端 执行相同的操作 接收数据包 对其进行加密 然后
  • jquery 改变 P 的 insidehtml 不起作用

    我有一个我认为是使用 jQuery 的简单选择来更改段落上的一些文本 它以传统方式完美运行 即 document getElementById message text innerHTML hello 但对于 jQuery 则不然 我已经检
  • 击败或满足 OS X memset(和 memset_pattern4)

    我的问题是基于另一个SO问题 为什么 mm stream ps 会产生 L1 LL 缓存未命中 https stackoverflow com questions 9068246 why does mm stream ps produce