Z boson..
13
有一种方法可以做到这一点,并不是那么困难.
您需要了解的主要内容是函数调用约定,对象格式和函数名称修改.
函数调用约定.
在32位模式下,Windows和Unix(即Linux,BSD,Mac OS X,...)使用相同的函数调用约定.
在64位模式下,Windows和Unix使用不同的函数调用约定.为了使用GCC编译的目标文件在64位模式下与MSVC一起使用,必须使用Windows函数调用约定.要使用gcc执行此操作,您可以使用mabi=ms例如:
g++ -c -mabi=ms -mavx -fopenmp -O3 foo.cpp
目标文件格式
Linux的目标文件格式是ELF,而Windows的目标文件格式是COFF/PE.为了在MSVC中使用用GCC编译的对象,需要将其从ELF转换为COFF.为此,您需要一个目标文件转换器.我使用Agner Fog的objconv.例如,要从ELF64转换为64位COFF64(PE32 +),请执行以下操作:
objconv -fcoff64 foo.o foo.obj
功能名称管理
由于函数重载,C++破坏了函数名称.GCC和MSVC的做法不同.为了解决这个问题,你可以继续使用函数名称external "C".
有关调用约定,对象格式和函数名称修改的更多详细信息,请参阅Agner Fog的手动调用约定.
下面是我用GCC编译的模块,然后在MSVC中使用(因为GCC更好地优化了它).我编译它-mabi=ms,将其转换为COFF64,objconv然后将其链接到运行完美的Visual Studio.
#include
extern "C" void inner(const int n, const float *a, const float *b, float *c, const int stridea, const int strideb, const int stridec) {
const int vec_size = 8;
__m256 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
tmp0 = _mm256_loadu_ps(&c[0*vec_size]);
tmp1 = _mm256_loadu_ps(&c[1*vec_size]);
tmp2 = _mm256_loadu_ps(&c[2*vec_size]);
tmp3 = _mm256_loadu_ps(&c[3*vec_size]);
tmp4 = _mm256_loadu_ps(&c[4*vec_size]);
tmp5 = _mm256_loadu_ps(&c[5*vec_size]);
tmp6 = _mm256_loadu_ps(&c[6*vec_size]);
tmp7 = _mm256_loadu_ps(&c[7*vec_size]);
for(int i=0; i
__m256 areg0 = _mm256_set1_ps(a[i]);
__m256 breg0 = _mm256_loadu_ps(&b[vec_size*(8*i + 0)]);
tmp0 = _mm256_add_ps(_mm256_mul_ps(areg0,breg0), tmp0);
__m256 breg1 = _mm256_loadu_ps(&b[vec_size*(8*i + 1)]);
tmp1 = _mm256_add_ps(_mm256_mul_ps(areg0,breg1), tmp1);
__m256 breg2 = _mm256_loadu_ps(&b[vec_size*(8*i + 2)]);
tmp2 = _mm256_add_ps(_mm256_mul_ps(areg0,breg2), tmp2);
__m256 breg3 = _mm256_loadu_ps(&b[vec_size*(8*i + 3)]);
tmp3 = _mm256_add_ps(_mm256_mul_ps(areg0,breg3), tmp3);
__m256 breg4 = _mm256_loadu_ps(&b[vec_size*(8*i + 4)]);
tmp4 = _mm256_add_ps(_mm256_mul_ps(areg0,breg4), tmp4);
__m256 breg5 = _mm256_loadu_ps(&b[vec_size*(8*i + 5)]);
tmp5 = _mm256_add_ps(_mm256_mul_ps(areg0,breg5), tmp5);
__m256 breg6 = _mm256_loadu_ps(&b[vec_size*(8*i + 6)]);
tmp6 = _mm256_add_ps(_mm256_mul_ps(areg0,breg6), tmp6);
__m256 breg7 = _mm256_loadu_ps(&b[vec_size*(8*i + 7)]);
tmp7 = _mm256_add_ps(_mm256_mul_ps(areg0,breg7), tmp7);
}
_mm256_storeu_ps(&c[0*vec_size], tmp0);
_mm256_storeu_ps(&c[1*vec_size], tmp1);
_mm256_storeu_ps(&c[2*vec_size], tmp2);
_mm256_storeu_ps(&c[3*vec_size], tmp3);
_mm256_storeu_ps(&c[4*vec_size], tmp4);
_mm256_storeu_ps(&c[5*vec_size], tmp5);
_mm256_storeu_ps(&c[6*vec_size], tmp6);
_mm256_storeu_ps(&c[7*vec_size], tmp7);
}