调度SIMD指令+ SIMDPP + qmake

列昂捷夫·格奥尔基(Leontyev Georgiy)

我正在开发一个利用SIMD指令集的QT小部件。我已经编译了3个版本:SSE3,AVX和AVX2(simdpp允许通过单个#define在它们之间进行切换)。

现在,我想要的是让窗口小部件根据最佳支持的指令集在这些实现之间自动切换。simdpp随附的指南利用了一些makefile魔术:

CXXFLAGS=""

test: main.o test_sse2.o test_sse3.o test_sse4_1.o test_null.o
    g++ $^ -o test

main.o: main.cc
    g++ main.cc $(CXXFLAGS) -c -o main.o

test_null.o: test.cc
    g++ test.cc -c $(CXXFLAGS) -DSIMDPP_EMIT_DISPATCHER \
        -DSIMDPP_DISPATCH_ARCH1=SIMDPP_ARCH_X86_SSE2 \
        -DSIMDPP_DISPATCH_ARCH2=SIMDPP_ARCH_X86_SSE3 \
        -DSIMDPP_DISPATCH_ARCH3=SIMDPP_ARCH_X86_SSE4_1 -o test_null.o

test_sse2.o: test.cc
    g++ test.cc -c $(CXXFLAGS) -DSIMDPP_ARCH_X86_SSE2 -msse2 -o test_sse2.o

test_sse3.o: test.cc
    g++ test.cc -c $(CXXFLAGS) -DSIMDPP_ARCH_X86_SSE3 -msse3 -o test_sse3.o

test_sse4_1.o: test.cc
    g++ test.cc -c $(CXXFLAGS) -DSIMDPP_ARCH_X86_SSE4_1 -msse4.1 -o test_sse4_1.o

这是指南的链接:http : //p12tic.github.io/libsimdpp/v2.0~rc2/libsimdpp/arch/dispatch.html

我不知道如何用qmake实现这种行为。有任何想法吗?

首先想到的是使用分派的代码创建一个共享库,并将其链接到项目。在这里,我再次陷入困境。App是跨平台的,这意味着它必须同时使用GCC和MSVC(准确地说是vc120)进行编译,这迫使Windows中使用nmake,我确实尝试过,但这就像我一生中最糟糕的经历。

在此先感谢世界各地的程序员!

Cgmillet

抱歉,如果这有点晚。希望我仍然可以提供帮助。

您需要考虑两个方面:编译时间和运行时间。

编译时-需要创建代码以支持不同的功能。运行时-需要创建代码来确定可以运行的功能。

您想要做的是创建一个调度程序...

FuncImpl.h:

#pragma once
void execAvx2();
void execAvx();
void execSse();
void execDefault();

FuncImpl.cpp:

// Compile this file once for each variant with different compiler settings.
#if defined(__AVX2__)
void execAvx2()
{
 // AVX2 impl
...
}

#elif defined (__AVX__)

void execAvx()
{
// AVX impl
...
}

#elif defined (__SSE4_2__)

void execSse()
{
 // Sse impl
...
}

#else

void execDefault()
{
 // Vanilla impl
...
}

#endif

DispatchFunc.cpp

#include "FuncImpl.h"

// Decide at runtime which code to run
void dispatchFunc()
{
     if(CheckCpuAvx2Flag())
     {
         execAvx2();
     } 
     else if(CheckCpuAvxFlag())
     {
         execAvx();
     }
     else if(CheckCpuSseFlags())
     {
         execSse();
     }
     else
     {
         execDefault();
     }
}

您可以做的是创建一组QMAKE_EXTRA_COMPILERS。

SampleCompiler.pri(对每个变体执行此操作):

MyCompiler.name = MyCompiler         # Name
MyCompiler.input = MY_SOURCES        # Symbol of the source list to compile
MyCompiler.dependency_type = TYPE_C
MyCompiler.variable_out = OBJECTS
# EXTRA_CXXFLAGS = -mavx / -mavx2 / -msse4.2
# _var = creates FileName_var.o => replace with own variant (_sse, etc)  
MyCompiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_IN_BASE}_var$${first(QMAKE_EXT_OBJ)}
MyCompiler.commands = $${QMAKE_CXX} $(CXXFLAGS) $${EXTRA_CXXFLAGS} $(INCPATH) -c ${QMAKE_FILE_IN} -o${QMAKE_FILE_OUT}
QMAKE_EXTRA_COMPILERS += MyCompiler   # Add my compiler

MyProject.pro

...
include(SseCompiler.pri)
include(AvxCompiler.pri)
include(Avx2Compiler.pri)
..

# Normal sources
# Will create FuncImpl.o and DispatchFunc.o
SOURCES += FuncImpl.cpp \
           DispatchFunc.cpp

# Give the other compilers their sources
# Will create FuncImpl_avx2.o FuncImpl_avx.o FuncImpl_sse.o
AVX2_SOURCES += FuncImpl.cpp
AVX_SOURCES += FuncImpl.cpp
SSE_SOURCES += FuncImpl.cpp

# Link all objects
...

您现在所需要的就是调用dispatchFunc()!

检查cpu标志是您的另一项练习:cpuid

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章