g++计时器与Intel oneAPI DPC++编译器兼容异常问题
HPCCG计时器在icpx编译下失效的问题分析与解决
问题现象
- 使用Intel oneAPI编译器
icpx编译HPCCG代码可成功编译,但所有时间统计值均为0,MFLOPS结果显示为inf - 使用
g++编译时,计时器功能正常,能输出有效性能统计数据
计时器实现代码
//@HEADER // ************************************************************************ // // HPCCG: Simple Conjugate Gradient Benchmark Code // Copyright (2006) Sandia Corporation // // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive // license for use of this work by or on behalf of the U.S. Government. // // BSD 3-Clause License // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // * Neither the name of the copyright holder nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Michael A. Heroux (maherou@sandia.gov) // // ************************************************************************ //@HEADER ///////////////////////////////////////////////////////////////////////// // Function to return time in seconds. // If compiled with no flags, return CPU time (user and system). // If compiled with -DWALL, returns elapsed time. ///////////////////////////////////////////////////////////////////////// #ifdef USING_MPI #include <mpi.h> // If this routine is compiled with -DUSING_MPI // then include mpi.h double mytimer(void) { return(MPI_Wtime()); } #elif defined(UseClock) #include <time.hpp> double mytimer(void) { clock_t t1; static clock_t t0=0; static double CPS = CLOCKS_PER_SEC; double d; if (t0 == 0) t0 = clock(); t1 = clock() - t0; d = t1 / CPS; return(d); } #elif defined(WALL) #include <cstdlib> #include <sys/time.h> #include <sys/resource.h> double mytimer(void) { struct timeval tp; static long start=0, startu; if (!start) { gettimeofday(&tp, NULL); start = tp.tv_sec; startu = tp.tv_usec; return(0.0); } gettimeofday(&tp, NULL); return( ((double) (tp.tv_sec - start)) + (tp.tv_usec-startu)/1000000.0 ); } #elif defined(UseTimes) #include <cstdlib> #include <sys/times.h> #include <unistd.h> double mytimer(void) { struct tms ts; static double ClockTick=0.0; if (ClockTick == 0.0) ClockTick = (double) sysconf(_SC_CLK_TCK); times(&ts); return( (double) ts.tms_utime / ClockTick ); } #else #include <cstdlib> #include <sys/time.h> #include <sys/resource.h> double mytimer(void) { struct rusage ruse; getrusage(RUSAGE_SELF, &ruse); return( (double)(ruse.ru_utime.tv_sec+ruse.ru_utime.tv_usec / 1000000.0) ); } #endif
编译输出对比
icpx编译结果
#********** Performance Summary (times in sec) ***********: Time Summary: Total : 0 DDOT : 0 WAXPBY : 0 SPARSEMV: 0 FLOPS Summary: Total : 9.536e+06 DDOT : 596000 WAXPBY : 894000 SPARSEMV: 8.046e+06 MFLOPS Summary: Total : inf DDOT : inf WAXPBY : inf SPARSEMV: inf
g++编译结果
#********** Performance Summary (times in sec) ***********: Time Summary: Total : 0.018251 DDOT : 0.001142 WAXPBY : 0.001825 SPARSEMV: 0.014805 FLOPS Summary: Total : 9.536e+06 DDOT : 596000 WAXPBY : 894000 SPARSEMV: 8.046e+06 MFLOPS Summary: Total : 522.492 DDOT : 521.891 WAXPBY : 489.863 SPARSEMV: 543.465
问题原因与解决方法
核心原因
icpx的优化逻辑(默认或显式指定的高优化级别)可能误将计时器相关代码优化:
- 默认使用的
getrusage获取CPU时间的逻辑,被编译器优化后返回值始终为0 - 静态变量初始化或时间差计算步骤被优化,导致时间差恒为0
解决步骤
- 禁用针对性优化:
- 编译时添加
-O0关闭所有优化,验证是否为优化导致的问题 - 若需保留部分优化,可针对计时器代码添加
-fno-inline或-foptimize-sibling-calls,避免计时器函数被内联优化
- 编译时添加
- 切换计时器实现:
- 编译时添加
-DWALL宏,使用gettimeofday实现的墙钟时间,该实现受优化影响更小 - 或添加
-DUseTimes,使用times系统调用获取CPU时间
- 编译时添加
- 升级编译器版本:
- 旧版Intel oneAPI编译器可能存在优化bug,升级至最新版本可修复该问题
内容的提问来源于stack exchange,提问作者Selorm K.aw
相关产品推荐
相关产品推荐

