2

I've installed Windows SDK 7.1 platform tools, and I opened a terminal named Microsoft Windows 7 x64 Debug Build Environment. Now I want to compile a C++ application (named main.cpp) using the cl.exe command. The compilation command is:

    cl main.cpp

Then, it outputs main.obj and main.exe file. But when I tried to run main.exe, it crashed after begin computing dist and before end computing dist. I think I should compile the application into x64 program. Could anybody give advice, please?

The main.cpp is as follows:

    #include <cstdio>
    #include <cstdlib>
    #ifdef _MSC_VER
    typedef unsigned __int32 uint32_t;
    typedef unsigned __int64 uint64_t;
    #include <intrin.h>
    #include <windows.h>
    #else
    #include <stdint.h>
    #include <sys/time.h>
    #include <unistd.h>
    #endif

    int main(int argc, char **argv) {

    int nTrn = 10;
    int nTst = 10;
    int nDim = 1; // 64 bit
    printf("allocate memory for feats.\n");
    uint64_t *trn_feat = new uint64_t[nTrn]; // nTrn x nDim
    uint64_t *tst_feat = new uint64_t[nTst]; // nTst x nDim

    printf("initialize the feats.\n");
    for(int i=0; i<nTrn; i++)
        trn_feat[i] = (((uint64_t) rand() <<  0) & 0x000000000000FFFFull) | 
                      (((uint64_t) rand() << 16) & 0x00000000FFFF0000ull) | 
                      (((uint64_t) rand() << 32) & 0x0000FFFF00000000ull) |
                      (((uint64_t) rand() << 48) & 0xFFFF000000000000ull);
    for(int i=0; i<nTst; i++)
        tst_feat[i] = (((uint64_t) rand() <<  0) & 0x000000000000FFFFull) | 
                      (((uint64_t) rand() << 16) & 0x00000000FFFF0000ull) | 
                      (((uint64_t) rand() << 32) & 0x0000FFFF00000000ull) |
                      (((uint64_t) rand() << 48) & 0xFFFF000000000000ull);

    printf("allocate memory for dist matrix.\n");
    uint64_t *dist = new uint64_t[nTrn*nTst];

    #ifdef _MSC_VER
    LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
    LARGE_INTEGER Frequency;
    QueryPerformanceFrequency(&Frequency);
    QueryPerformanceCounter(&StartingTime);
    #else
    struct timeval start, end;
    long seconds, useconds;
    double mtime;
    gettimeofday(&start, NULL);
    #endif

    printf("begin computing dist.\n");
    for(int iter=0; iter<100; iter++) {
        for(int i=0; i<nTrn; i++) {
             for(int j=0; j<nTst; j++) {
                 uint64_t n = (trn_feat[i] ^ tst_feat[j]);
    #ifdef _MSC_VER
                 dist[i*nTst + j] = __popcnt64(n);
    #else
                 dist[i*nTst + j] = __builtin_popcountll(n);
    #endif
             }     
        }
    }
    printf("end computing dist.\n");

    #ifdef _MSC_VER
    QueryPerformanceCounter(&EndingTime);
    ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
    ElapsedMicroseconds.QuadPart *= 1000000;
    ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
    double mtime = (double)ElapsedMicroseconds.QuadPart;
    printf("Average time: %.6f nanoseconds\n", (1e6*mtime)/100/(nTrn*nTst));
    #else
    gettimeofday(&end, NULL);
    seconds = end.tv_sec - start.tv_sec;
    useconds = end.tv_usec - start.tv_usec;
    mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
    printf("Total elapsed time: %.6f milliseconds\n", mtime);
    printf("Average time: %.6f nanoseconds\n", (1e6*mtime)/1000/(nTrn*nTst));
    #endif

    delete[] trn_feat;
    delete[] tst_feat;
    delete[] dist;

    }
mining
  • 3,557
  • 5
  • 39
  • 66
  • So what is your question? How to specify the target platform? How to fix your bug? – IInspectable Apr 14 '16 at 13:29
  • @IInspectable, thank you! Is there a bug in the code? It seems in `Ubuntu` the code can be run OK. – mining Apr 14 '16 at 13:46
  • You aren't compiling the same code for Windows and Ubuntu, so how is the fact that the program appears to run fine on Ubuntu any indication, that it doesn't contain a bug? – IInspectable Apr 14 '16 at 13:48
  • @IInspectable, before adding the Windows code, I can run OK in Ubuntu. – mining Apr 14 '16 at 13:54
  • Hi, @IInspectable, I have tried to compile the code in Ubuntu again, it can run OK. Could you please show where the bug is? Thanks! – mining Apr 14 '16 at 14:09
  • @IInspectable, the code can be compiled in Windows. But it runs crashed at `__popcnt64`. – mining Apr 14 '16 at 14:14
  • And what did you learn from reading the documentation for [__popcnt64](https://msdn.microsoft.com/en-us/library/bb385231.aspx)? *"In 32-bit mode there are no 64-bit general-purpose registers, hence no 64-bit popcnt."* and *"To determine hardware support for the popcnt instruction, call the __cpuid intrinsic with InfoType=0x00000001 and check bit 23 of CPUInfo[2] (ECX). This bit is 1 if the instruction is supported, and 0 otherwise."* seem to be fairly important hints. – IInspectable Apr 14 '16 at 14:16
  • @IInspectable, thanks for the reference. So if we compiled the code using 64-bit mode, it can run OK? – mining Apr 14 '16 at 14:22
  • @IInspectable, yes, in [https://github.com/openMVG/openMVG/blob/master/src/openMVG/matching/metric_hamming.hpp], Line 95, it first checked the platform. This is more safe. – mining Apr 14 '16 at 14:23
  • @IInspectable, I add a platform check code in `main` function, it shows the machine is a 64-bit platform. The check code is `#if __amd64__ || __x86_64__ || _WIN64 || _M_X64 \n printf("Yes, it's a 64-bit platform.\n"); \n #else \n printf("No, it's not a 64-bit platform.\n"); \n endif`. Then I compile the code, it shows the machine is a 64-bit platform. So I think the problem is how to compile the code into 64-bit mode. – mining Apr 14 '16 at 14:28
  • You don't seem to understand, how preprocessor directives work. If your previous snippet compiles to code that displays *"Yes, it's a 64-bit platform."*, then you **are** compiling for a 64-bit target. You can't just go around and copy random bits and pieces off the internet, and hope that everything magically works. You will have to know, what you are doing. – IInspectable Apr 14 '16 at 14:45
  • @IInspectable, thanks! I think what you mean is the processor didn't support 64-bit mode. – mining Apr 14 '16 at 14:52
  • @IInspectable, after checking the supported instruction set of the CPU, it seems the CPU doesn't support POPCNT. The referernce `https://msdn.microsoft.com/en-us/library/hskdteyh.aspx` is really helpful. Thanks you for your kindly comments and suggestions! – mining Apr 15 '16 at 05:48
  • @IInspectable, it seems the `__popcnt64` in `Windows Visual C++` is much faster than the `__builtin_popcountll` in `GCC 4.8`. In the above code, the `__popcnt64` only needs 2.45 nanoseconds, while the latter needs 4.45 nanoseconds. – mining Apr 17 '16 at 00:01

1 Answers1

0

The following is the possible answer:

  1. install Visual Studio Community 2015
  2. Open the Visual Studio x64 terminal from the Visual Studio Group
  3. cl.exe main.cpp /link /machine:x64

Then a main.exe is outputed.

To run the main.exe, there are two necessary conditions:

  1. The machine or CPU can support the __popcnt64 instruction set. To check whether the machine supports it, refer __cpuid.
  2. The Windows operating system is 64 bit.
mining
  • 3,557
  • 5
  • 39
  • 66