Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android NDK:vector.resize()太慢,与分配有关吗?_Android_C++_Android Ndk - Fatal编程技术网

Android NDK:vector.resize()太慢,与分配有关吗?

Android NDK:vector.resize()太慢,与分配有关吗?,android,c++,android-ndk,Android,C++,Android Ndk,我在Android NDK中遇到了一件非常奇怪的事情 我有一个循环 #include <chrono> #include <android/log.h> #include <vector> while (true) { const int sz = 2048*2048*3; std::vector<unsigned char> v; { auto startTime

我在Android NDK中遇到了一件非常奇怪的事情

我有一个循环

#include <chrono>
#include <android/log.h>
#include <vector>

while (true)
    {
        const int sz = 2048*2048*3;
        std::vector<unsigned char> v;
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(sz);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 1", "v.resize(%d) time : %lld\n", sz, duration.count());
        }
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(0);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 2", "v.resize(0) time : %lld\n", duration.count());
        }
        {
            auto startTime = std::chrono::system_clock::now();
            v.resize(sz);
            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - startTime);
            __android_log_print(ANDROID_LOG_ERROR, "READFILE 3", "v.resize(%d) time : %lld\n", sz, duration.count());
        }
    }
因此,首先

  • 正如你所看到的,我只为
    resize(0)
    得到了550毫秒。。。应该是 最大1微秒,非毫秒
  • 其次,为什么
    resize(size)
    如果载体的容量不变
  • 这是两种非常奇怪的行为

    如果您不相信我的话,欢迎您自行查看这段代码:)但只需查看Android NDK,而不是Visual Studio项目,因为它可以正常工作

    它看起来真的像虫子

    或者我做错了什么

    编辑

    我检查了一下,如果转到
    resize()
    方法,我会遇到这样的循环

    template <class _Tp, class _Allocator>
    inline _LIBCPP_INLINE_VISIBILITY
    void
    __vector_base<_Tp, _Allocator>::__destruct_at_end(pointer __new_last) _NOEXCEPT
    {
        pointer __soon_to_be_end = __end_;
        while (__new_last != __soon_to_be_end)
            __alloc_traits::destroy(__alloc(), _VSTD::__to_raw_pointer(--__soon_to_be_end));
        __end_ = __new_last;
    }
    
    模板
    内联\u LIBCPP\u内联\u可见性
    无效的
    __向量基::uuu destruct_u在_u端(指针uu new_ulast)u无异常
    {
    指针uuu soon_uto_ube_end=uuu end;
    while(\uuuu new\uu last!=\uuuuu soon\uu to\uu be\uu end)
    __alloc_traits::destroy(u_alloc(),_VSTD::u to_raw_pointer(--u soon_to_be_end));
    __结束=新的最后一个;
    }
    
    所以,这意味着在resize范围内的每个元素上都有一个循环,并调用destroy

    如果你持有的不是有析构函数的平凡对象,但是如果你持有的是向量(就像我的例子)中的int对象是平凡的,它们没有析构函数,那么就没有问题了,所以。。。这是一种非常奇怪的行为,如何从实际上没有析构函数的对象调用析构函数


    它看起来像编译器bug吗?

    首先,许多库功能的实现强烈依赖于编译器优化。删除容器中的对象可以调用destroy,而这反过来对于微不足道的可破坏对象将无能为力。若它什么也不做,那个么编译器将优化所有逻辑。在STL中销毁对象涉及很多逻辑。本质上,调用destroy是为了确保它处理所有情况,包括自定义分配器。它必须编译,因此对于普通类型,它必须解析为定义的内容,而不执行任何操作仍然是定义的内容。只是让代码尽可能干净。单一责任,deallocator决定如何以及是否需要销毁对象

    至于你的主要问题,你使用优化吗?这是第一个也是最重要的问题。任何没有优化的代码都可以保证正常工作。即使引用提供的复杂性对于未优化的代码也可能不同。您可以清楚地看到,第一次重新分配花费的时间几乎是原来的两倍,其余时间相当稳定


    你是否有更好的时间与其他类型的操作?您是否尝试与普通阵列性能进行比较?

    除了Maciej的回答和Andy的评论之外,让我们检查生成的代码

    使用此生成文件:

    CXX = $(NDKPATH)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++
    CC = $(NDKPATH)/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++
    INC = -I$(NDKPATH)/cxx-stl/llvm-libc++/include/
    LIB = -L$(NDKPATH)/cxx-stl/llvm-libc++/lib/
    CXXFLAGS = -ggdb -O$(OPTLEVEL)
    
    .PHONY: all clean dump
    
    all: dump
    
    dump: test
        $(NDKPATH)/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/objdump -d -C test | gawk '/<big|<small|::resize/ {p=1} /^$$/ {p=0} {if (p) print $0}'
    
    clean:
        $(RM) test.o test
    
    test: test.o
    
    使用
    -O2
    ,编译器可以为我们进行大量优化

    首先,
    resize()
    完全消失了;它已被删除,因为没有人需要它了

    big()。因为我没有运行过这段代码,所以我不能断言这对速度有多大帮助

    small()。如果(v.begin!=v.end)v.end=v.begin
    ,它基本上变成了
    。这当然会非常快

    ndk-vector-speed$ make clean && OPTLEVEL=2 make dump
    rm -f test.o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++ -ggdb -O2   -c -o test.o test.cpp
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++   test.o   -o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/objdump -d -C test | gawk '/<big|<small|::resize/ {p=1} /^$/ {p=0} {if (p) print }'
    0000000000000e64 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         e64:   a9402408    ldp x8, x9, [x0]
         e68:   5292d00a    mov w10, #0x9680                    // #38528
         e6c:   72a0130a    movk    w10, #0x98, lsl #16
         e70:   cb080129    sub x9, x9, x8
         e74:   9342fd2b    asr x11, x9, #2
         e78:   eb0a017f    cmp x11, x10
         e7c:   54000062    b.cs    e88 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x24>
         e80:   cb0b0141    sub x1, x10, x11
         e84:   14000011    b   ec8 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::__append(unsigned long)>
         e88:   528b400a    mov w10, #0x5a00                    // #23040
         e8c:   72a04c4a    movk    w10, #0x262, lsl #16
         e90:   eb0a013f    cmp x9, x10
         e94:   540000a0    b.eq    ea8 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x44>
         e98:   528b4009    mov w9, #0x5a00                 // #23040
         e9c:   72a04c49    movk    w9, #0x262, lsl #16
         ea0:   8b090108    add x8, x8, x9
         ea4:   f9000408    str x8, [x0,#8]
         ea8:   d65f03c0    ret
    0000000000000eac <small(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         eac:   a9402408    ldp x8, x9, [x0]  // load the first two values (begin and end) from v
         eb0:   eb08013f    cmp x9, x8        // compare them
         eb4:   54000040    b.eq    ebc <small(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x10>
                                              // skip to 'ret' if they were equal
         eb8:   f9000408    str x8, [x0,#8]   // write v.begin to v.end
         ebc:   d65f03c0    ret               // return.
    
    ndk矢量速度$make clean&&OPTLEVEL=2 make dump
    rm-f测试
    /home/snild/.androidsdk/ndk bundle/toolschains/llvm/prebuild/linux-x86_64/bin/aarch64-linux-android29-clang++-ggdb-O2-c-o test.o test.cpp
    /home/snild/.androidsdk/ndk bundle/toolschains/llvm/prebuild/linux-x86_64/bin/aarch64-linux-android29-clang++test.o-o测试
    
    /home/snild/.androidsdk/ndk bundle/toolschains/llvm/prebuild/linux-x86_64/aarch64-linux-android/bin/objdump-d-C test | gawk'/感谢@snild Dolkow、@Maciej Załucki和@Andy Jewell

    最终问题在优化级别

    如果您使用
    CMake
    ,请使用此代码

    target\u compile\u选项(opende专用
    "$"
    "$"
    )
    
    但选择您需要的优化级别

    如果使用
    Application.mk
    请使用此代码


    “最大应为1微秒”什么是微秒?检查
    调整大小(0)
    是否将容量更改为0。从技术上讲,它可以调整大小(0)
    会使所有迭代器无效。顺便说一句,在测量时间时,您可能应该使用
    稳定时钟
    (或者
    高分辨率时钟
    ,如果
    是稳定的
    真的
    ),您使用的优化级别是什么?这似乎是你在-O0时会看到的那种情况,但在-O2时可能会消失。@AndyJewell我如何检查实际的优化级别?根据我的gradle文件,它是标准的“getDefaultProguardFile('proguard-android.txt')”,从技术上讲,android NDK使用LLVM libc++,而不是GNU stdlibc++,但实现非常相似。这是和的相应来源。我已经再次发布了这个问题,但是有一点不同,你能看一下吗
    #include <vector>
    
    using std::vector;
    
    void big(vector<int>& v) {
        v.resize(10000000);
    }
    
    void small(vector<int>& v) {
        v.resize(0);
    }
    
    int main() {
        return 0;
    }
    
    ndk-vector-speed$ export NDKPATH=~/.androidsdk/ndk-bundle
    ndk-vector-speed$ make clean && OPTLEVEL=0 make dump
    rm -f test.o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++ -ggdb -O0   -c -o test.o test.cpp
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++   test.o   -o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/objdump -d -C test | gawk '/<big|<small|::resize/ {p=1} /^$/ {p=0} {if (p) print }'
    0000000000000f04 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         f04:   d10083ff    sub sp, sp, #0x20
         f08:   a9017bfd    stp x29, x30, [sp,#16]
         f0c:   910043fd    add x29, sp, #0x10
         f10:   d292d001    mov x1, #0x9680                 // #38528
         f14:   f2a01301    movk    x1, #0x98, lsl #16
         f18:   f90007e0    str x0, [sp,#8]
         f1c:   f94007e0    ldr x0, [sp,#8]
         f20:   94000013    bl  f6c <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)>
         f24:   a9417bfd    ldp x29, x30, [sp,#16]
         f28:   910083ff    add sp, sp, #0x20
         f2c:   d65f03c0    ret
    0000000000000f30 <small(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         f30:   d10083ff    sub sp, sp, #0x20
         f34:   a9017bfd    stp x29, x30, [sp,#16]
         f38:   910043fd    add x29, sp, #0x10
         f3c:   d2800001    mov x1, #0x0                    // #0
         f40:   f90007e0    str x0, [sp,#8]
         f44:   f94007e0    ldr x0, [sp,#8]
         f48:   94000009    bl  f6c <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)>
         f4c:   a9417bfd    ldp x29, x30, [sp,#16]
         f50:   910083ff    add sp, sp, #0x20
         f54:   d65f03c0    ret
    0000000000000f6c <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)>:
         f6c:   d100c3ff    sub sp, sp, #0x30
         f70:   a9027bfd    stp x29, x30, [sp,#32]
         f74:   910083fd    add x29, sp, #0x20
         f78:   f81f83a0    stur    x0, [x29,#-8]
         f7c:   f9000be1    str x1, [sp,#16]
         f80:   f85f83a0    ldur    x0, [x29,#-8]
         f84:   f90003e0    str x0, [sp]
         f88:   94000020    bl  1008 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::size() const>
         f8c:   f90007e0    str x0, [sp,#8]
         f90:   f94007e0    ldr x0, [sp,#8]
         f94:   f9400be1    ldr x1, [sp,#16]
         f98:   eb01001f    cmp x0, x1
         f9c:   1a9f27e8    cset    w8, cc
         fa0:   37000048    tbnz    w8, #0, fa8 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)+0x3c>
         fa4:   14000007    b   fc0 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)+0x54>
         fa8:   f9400be8    ldr x8, [sp,#16]
         fac:   f94007e9    ldr x9, [sp,#8]
         fb0:   eb090101    subs    x1, x8, x9
         fb4:   f94003e0    ldr x0, [sp]
         fb8:   9400001e    bl  1030 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::__append(unsigned long)>
         fbc:   14000010    b   ffc <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)+0x90>
         fc0:   f94007e8    ldr x8, [sp,#8]
         fc4:   f9400be9    ldr x9, [sp,#16]
         fc8:   eb09011f    cmp x8, x9
         fcc:   1a9f97ea    cset    w10, hi
         fd0:   3700004a    tbnz    w10, #0, fd8 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)+0x6c>
         fd4:   1400000a    b   ffc <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::resize(unsigned long)+0x90>
         fd8:   b27e03e8    orr x8, xzr, #0x4
         fdc:   f94003e9    ldr x9, [sp]
         fe0:   f9400129    ldr x9, [x9]
         fe4:   f9400bea    ldr x10, [sp,#16]
         fe8:   9b0a7d08    mul x8, x8, x10
         fec:   8b080128    add x8, x9, x8
         ff0:   f94003e0    ldr x0, [sp]
         ff4:   aa0803e1    mov x1, x8
         ff8:   94000054    bl  1148 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::__destruct_at_end(int*)>
         ffc:   a9427bfd    ldp x29, x30, [sp,#32]
        1000:   9100c3ff    add sp, sp, #0x30
        1004:   d65f03c0    ret
    
    ndk-vector-speed$ make clean && OPTLEVEL=2 make dump
    rm -f test.o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++ -ggdb -O2   -c -o test.o test.cpp
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android29-clang++   test.o   -o test
    /home/snild/.androidsdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/aarch64-linux-android/bin/objdump -d -C test | gawk '/<big|<small|::resize/ {p=1} /^$/ {p=0} {if (p) print }'
    0000000000000e64 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         e64:   a9402408    ldp x8, x9, [x0]
         e68:   5292d00a    mov w10, #0x9680                    // #38528
         e6c:   72a0130a    movk    w10, #0x98, lsl #16
         e70:   cb080129    sub x9, x9, x8
         e74:   9342fd2b    asr x11, x9, #2
         e78:   eb0a017f    cmp x11, x10
         e7c:   54000062    b.cs    e88 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x24>
         e80:   cb0b0141    sub x1, x10, x11
         e84:   14000011    b   ec8 <std::__ndk1::vector<int, std::__ndk1::allocator<int> >::__append(unsigned long)>
         e88:   528b400a    mov w10, #0x5a00                    // #23040
         e8c:   72a04c4a    movk    w10, #0x262, lsl #16
         e90:   eb0a013f    cmp x9, x10
         e94:   540000a0    b.eq    ea8 <big(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x44>
         e98:   528b4009    mov w9, #0x5a00                 // #23040
         e9c:   72a04c49    movk    w9, #0x262, lsl #16
         ea0:   8b090108    add x8, x8, x9
         ea4:   f9000408    str x8, [x0,#8]
         ea8:   d65f03c0    ret
    0000000000000eac <small(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)>:
         eac:   a9402408    ldp x8, x9, [x0]  // load the first two values (begin and end) from v
         eb0:   eb08013f    cmp x9, x8        // compare them
         eb4:   54000040    b.eq    ebc <small(std::__ndk1::vector<int, std::__ndk1::allocator<int> >&)+0x10>
                                              // skip to 'ret' if they were equal
         eb8:   f9000408    str x8, [x0,#8]   // write v.begin to v.end
         ebc:   d65f03c0    ret               // return.
    
    target_compile_options(opende PRIVATE
    "$<$<CONFIG:RELEASE>:-O3>"
    "$<$<CONFIG:DEBUG>:-O3>"
    )