コード例 #1
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
def find_gcc_compiler():
    best = None
    for program in GCC_BINARIES:
        try:
            # currently the arm version of gcc from homebrew doesn't come with libasan and libubsan in which case we don't want to choose gcc
            if platform.system() == 'Darwin' and platform.machine() == 'arm64':
                args = [
                    program, '-xc++', '-fsanitize=address',
                    '-fsanitize=undefined', '-', '-o', '/dev/null'
                ]
                log_command(args, 2)
                assert (subprocess.run(args,
                                       timeout=10,
                                       input="int main() { } ",
                                       text=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE).returncode == 0)

            args = [program, '-dM', '-fopenmp', '-E', '-']
            log_command(args, 2)
            output = subprocess.run(args,
                                    input='',
                                    timeout=10,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    encoding='utf-8',
                                    errors='utf-8')
            if output.returncode == 0:
                lines = output.stdout.split('\n')
                matches = [
                    re.match('^#define (\\w+) (.*)$', line) for line in lines
                ]
                macros = {
                    match.group(1): match.group(2)
                    for match in matches if match is not None
                }

                if '__clang__' not in macros and '_OPENMP' in macros:
                    # We don't want to choose clang in any case
                    try:
                        version = (int(macros['__GNUC__']),
                                   int(macros['__GNUC_MINOR__']),
                                   int(macros['__GNUC_PATCHLEVEL__']))
                        if version[0] >= MIN_GCC and (best is None
                                                      or best[1] < version):
                            best = (program, version)
                    except TypeError:
                        pass

        except FileNotFoundError:
            pass
        except AssertionError:
            pass
    if best is not None:
        return GccCompiler(best[0])
コード例 #2
0
    def run(self, config, args: List[str], timeout: float) -> AsanRunnerOutput:
        env = os.environ.copy()
        env.update(self.env)
        if 'ASAN_OPTIONS' in env:
            env['ASAN_OPTIONS'] += ':log_path=/tmp/asan.log'
        else:
            env['ASAN_OPTIONS'] = 'log_path=/tmp/asan.log'

        ppc_output_read, ppc_output_write = os.pipe()
        env['PPC_OUTPUT'] = str(ppc_output_write)

        log_command(args)
        process = subprocess.Popen(args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.DEVNULL,
                                   env=env,
                                   encoding='utf-8',
                                   errors='utf-8',
                                   pass_fds=(ppc_output_write, ))
        os.close(ppc_output_write)

        try:
            stdout, stderr = process.communicate(None, timeout=timeout)
            run_successful = process.returncode == 0
            timed_out = False
        except subprocess.TimeoutExpired:
            timed_out = True
            run_successful = False
            try:
                # Ask nicely to terminate before killing
                process.terminate()
                stdout, stderr = process.communicate(None, timeout=1)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate(None)

        # Read Asan output
        if os.path.exists(f"/tmp/asan.log.{process.pid}"):
            with open(f"/tmp/asan.log.{process.pid}") as f:
                asanoutput = f.read()
            # Try to delete the output file
            os.remove(f"/tmp/asan.log.{process.pid}")
        else:
            asanoutput = None

        if run_successful:
            output = os.fdopen(ppc_output_read, 'r').read()
            results = config.parse_output(output)
        else:
            os.close(ppc_output_read)
            results = []

        return AsanRunnerOutput(run_successful, timed_out, stdout, stderr,
                                timeout, asanoutput, *results)
コード例 #3
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
 def is_valid(self) -> bool:
     try:
         args = [self.program, '-dM', '-fopenmp', '-E', '-']
         log_command(args, 2)
         return subprocess.run(args,
                               input='',
                               timeout=10,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               encoding='utf-8',
                               errors='utf-8').returncode == 0
     except AssertionError:
         return False
     except subprocess.TimeoutExpired:
         sys.exit(
             'Testing compiler took too much time, killed the process.')
コード例 #4
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
def find_nvcc_compiler():
    best = None
    for program in NVCC_BINARIES:
        try:
            log_command([program], 2)
            output = subprocess.run([program],
                                    input='',
                                    timeout=10,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    encoding='utf-8',
                                    errors='utf-8')
            if output.returncode == 1:
                best = (program, 0)
        except FileNotFoundError:
            pass
    if best is not None:
        return NvccCompiler(best[0])
コード例 #5
0
    def run(self, config, args: List[str],
            timeout: Optional[float]) -> RunnerOutput:
        env = os.environ.copy()

        ppc_output_read, ppc_output_write = os.pipe()
        env['PPC_OUTPUT'] = str(ppc_output_write)

        env['PPC_PERF'] = 'default'

        log_command(args)
        process = subprocess.Popen(args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.DEVNULL,
                                   env=env,
                                   encoding='utf-8',
                                   errors='utf-8',
                                   pass_fds=(ppc_output_write, ))
        os.close(ppc_output_write)

        try:
            stdout, stderr = process.communicate(None, timeout=timeout)
            run_successful = process.returncode == 0
            timed_out = False
        except subprocess.TimeoutExpired:
            run_successful = False
            timed_out = True
            try:
                # Ask nicely to terminate before killing
                process.terminate()
                stdout, stderr = process.communicate(None, timeout=1)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate(None)

        if run_successful:
            output = os.fdopen(ppc_output_read, 'r').read()
            results = config.parse_output(output)
        else:
            os.close(ppc_output_read)
            results = []

        return RunnerOutput(run_successful, timed_out, stdout, stderr, timeout,
                            *results)
コード例 #6
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
    def __get_version(program: str):
        try:
            args = [program, '-dM', '-fopenmp', '-E', '-']
            if platform.system() == 'Darwin':
                args = [
                    program, '-dM', '-Xpreprocessor', '-fopenmp', '-E', '-'
                ]
            log_command(args, 2)
            output = subprocess.run(args,
                                    input='',
                                    timeout=10,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    encoding='utf-8',
                                    errors='utf-8')
            if output.returncode == 0:
                lines = output.stdout.split('\n')
                matches = [
                    re.match('^#define (\\w+) (.*)$', line) for line in lines
                ]
                macros = {
                    match.group(1): match.group(2)
                    for match in matches if match is not None
                }
                try:
                    apple = True if 'Apple' in macros['__VERSION__'] else False
                except:
                    apple = None
                if '__clang__' in macros and '_OPENMP' in macros:
                    try:
                        return [(int(macros['__clang_major__']),
                                 int(macros['__clang_minor__']),
                                 int(macros['__clang_patchlevel__'])), apple]
                    except TypeError:
                        pass

        except FileNotFoundError:
            pass

        return [None, None]
コード例 #7
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
    def compile(self, out_file: str = 'a.out') -> CompilerOutput:
        try:
            args = [self.program
                    ] + self.common_flags + self.flags + self.sources + [
                        '-o', out_file
                    ]
            log_command(args)
            result = subprocess.run(args,
                                    timeout=10,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    encoding='utf-8',
                                    errors='utf-8')
        except subprocess.TimeoutExpired:
            return CompilerOutput(
                '',
                'Compilation process took too much time, killed the process',
                -1)

        return CompilerOutput(result.stdout[:MAX_COMPILER_OUTPUT],
                              result.stderr[:MAX_COMPILER_OUTPUT],
                              result.returncode)
コード例 #8
0
 def is_valid(self) -> bool:
     try:
         args = [self.program, '-dM', '-fopenmp', '-E', '-']
         if isinstance(self,
                       ClangCompiler) and platform.system() == 'Darwin':
             args = [
                 self.program, '-dM', '-Xpreprocessor', '-fopenmp', '-E',
                 '-'
             ]
         log_command(args)
         return subprocess.run(args,
                               input='',
                               timeout=10,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               encoding='utf-8',
                               errors='utf-8').returncode == 0
     except AssertionError:
         return False
     except subprocess.TimeoutExpired:
         sys.exit(
             'Testing compiler took too much time, killed the process.')
コード例 #9
0
    def run(self, config, args: List[str],
            timeout: float) -> MemcheckRunnerOutput:
        env = os.environ.copy()
        env.update(self.env)

        ppc_output_read, ppc_output_write = os.pipe()
        env['PPC_OUTPUT'] = str(ppc_output_write)

        # Run with memcheck
        memcheck_output_file = tempfile.NamedTemporaryFile('r')
        args = [
            'cuda-memcheck',
            '--tool',
            self.tool,
            '--log-file',
            memcheck_output_file.name,
            '--error-exitcode',
            '1',
            '--prefix',
            ' ',
            '--print-limit',
            '1000',
            *(['--leak-check', 'full'] if self.tool == 'memcheck' else []),
            '--',
        ] + args

        log_command(args)
        process = subprocess.Popen(args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.DEVNULL,
                                   env=env,
                                   encoding='utf-8',
                                   errors='utf-8',
                                   pass_fds=(ppc_output_write, ))
        os.close(ppc_output_write)

        try:
            stdout, stderr = process.communicate(None, timeout=timeout)
            run_successful = process.returncode == 0
            timed_out = False
        except subprocess.TimeoutExpired:
            timed_out = True
            run_successful = False
            try:
                # Ask nicely to terminate before killing
                process.terminate()
                stdout, stderr = process.communicate(None, timeout=1)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate(None)

        # Read memcheck output
        memcheckoutput = memcheck_output_file.read()
        no_outputs = [
            '  CUDA-MEMCHECK\n  LEAK SUMMARY: 0 bytes leaked in 0 allocations\n  ERROR SUMMARY: 0 errors\n',
            '  CUDA-MEMCHECK\n  RACECHECK SUMMARY: 0 hazards displayed (0 errors, 0 warnings) \n',
            '  CUDA-MEMCHECK\n  ERROR SUMMARY: 0 errors\n',
        ]
        if memcheckoutput in no_outputs:
            memcheckoutput = None

        if run_successful:
            output = os.fdopen(ppc_output_read, 'r').read()
            results = config.parse_output(output)
        else:
            os.close(ppc_output_read)
            results = []

        return MemcheckRunnerOutput(run_successful, timed_out, stdout, stderr,
                                    timeout, memcheckoutput, *results)
コード例 #10
0
    def run(self, config, args: List[str],
            timeout: Optional[float]) -> RunnerOutput:
        env = os.environ.copy()

        ppc_output_read, ppc_output_write = os.pipe()
        env['PPC_OUTPUT'] = str(ppc_output_write)

        env['PPC_PERF'] = 'default'

        # Run with nvprof
        nvprof_output_file = tempfile.NamedTemporaryFile('r')
        args = [
            'nvprof',
            '--csv',
            '--log-file',
            nvprof_output_file.name,
            '--normalized-time-unit',
            's',
            '--print-gpu-trace',
            '--',
        ] + args

        log_command(args)
        process = subprocess.Popen(args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.DEVNULL,
                                   env=env,
                                   encoding='utf-8',
                                   errors='utf-8',
                                   pass_fds=(ppc_output_write, ))
        os.close(ppc_output_write)

        try:
            stdout, stderr = process.communicate(None, timeout=timeout)
            run_successful = process.returncode == 0
            timed_out = False
        except subprocess.TimeoutExpired:
            run_successful = False
            timed_out = True
            try:
                # Ask nicely to terminate before killing
                process.terminate()
                stdout, stderr = process.communicate(None, timeout=1)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate(None)

        # Read nvprof output
        def get_scale(unit: str, base=1000) -> float:
            if unit == 'm':
                return base**-1
            elif unit == 'K':
                return base**1
            elif unit == 'M':
                return base**2
            elif unit == 'G':
                return base**3
            elif unit == 'T':
                return base**4
            elif unit == 'P':
                return base**5
            return 1

        def split_unit(unit: str) -> Tuple[str, float]:
            if unit.endswith('B'):
                scale = get_scale(unit[:-1], 1024)
                return ('bytes', scale)
            elif unit.endswith('B/s'):
                scale = get_scale(unit[:-3], 1024)
                return ('bytes/s', scale)
            elif unit.endswith('s'):
                scale = get_scale(unit[:-1])
                return ('s', scale)
            return ('', 1.)

        def normalize_units(row: Dict[str, Any], units: Dict[str, str]):
            normalized = {}
            for k, v in row.items():
                suffix, scale = split_unit(units[k])
                if suffix or scale != 1:
                    k = k + ' ' + suffix
                    if v:
                        v = float(v) * scale
                    else:
                        v = None
                normalized[k] = v
            return normalized

        nvprofoutput_raw = nvprof_output_file.read()
        nvprof_statistics = {}
        try:
            # First line should look something like
            # ==[PID]== NVPROF is profiling process [PID], command: [some command]
            # Let's parse the PID part and use ==PID== as a comment marker in the future
            first_line = nvprofoutput_raw.split('\n', 1)[0]
            m = re.match(r'^==(\d+)== (.*)', first_line)
            pid = m.group(1)
            section = m.group(2)
            r = re.compile(fr'^=={re.escape(pid)}== (.*?)$', re.MULTILINE)
            pos = m.end()
            while True:
                m = r.search(nvprofoutput_raw, pos)
                if m is None:
                    end = -1
                else:
                    end = m.start()

                content = nvprofoutput_raw[pos:end].strip()

                if section == 'Profiling result:':
                    gpu_trace = list(
                        csv.DictReader(io.StringIO(content),
                                       dialect=csv.unix_dialect))
                    # Normalize units
                    units = gpu_trace[0]
                    gpu_trace = gpu_trace[1:]

                    if len(gpu_trace) <= 100:
                        gpu_trace = [
                            normalize_units(row, units) for row in gpu_trace
                        ]
                        nvprof_statistics['gpu_trace'] = gpu_trace
                    else:
                        nvprof_statistics['gpu_trace'] = None
                        nvprof_statistics[
                            'gpu_trace_message'] = "Too long GPU trace."

                if m is None:
                    break
                section = m.group(1)
                pos = m.end()
        except:
            # Parsing nvprof output failed
            pass

        if run_successful:
            output = os.fdopen(ppc_output_read, 'r').read()
            results = config.parse_output(output)
        else:
            os.close(ppc_output_read)
            results = []

        return NvprofRunnerOutput(nvprofoutput_raw, nvprof_statistics,
                                  run_successful, timed_out, stdout, stderr,
                                  timeout, *results)
コード例 #11
0
ファイル: compiler.py プロジェクト: Westblat/ppc-gpu
    def add_omp_flags(self) -> 'Compiler':
        # Apple clang doesn't have openmp compiled so we want to include the homebrew package.
        if platform.system() == 'Darwin':
            try:
                brew_dir_command = ['brew', '--prefix']
                log_command(brew_dir_command)
                brew_dir = subprocess.run(brew_dir_command,
                                          timeout=10,
                                          stdout=subprocess.PIPE,
                                          stderr=subprocess.PIPE,
                                          encoding='utf-8').stdout.strip()
            except FileNotFoundError:
                message = '''It seems that you don't have Homebrew installed.
It is needed if you want to run OpenMP tasks on macOS.
It would be great if you could install Homebrew from:

    https://brew.sh/

After that you need to install libomp with this command:

    brew install libomp

'''
                if platform.machine() != 'arm64':
                    message += '''
Or alternatively you can try to install GCC and use it instead of Clang:

    brew install gcc

'''
                message += '''Once you have done that, please try to run the same command again,
I should be able to find the right packages and compilers then!'''
                sys.exit(message)

            try:
                brew_libomp_command = ['brew', 'list', 'libomp']
                log_command(brew_libomp_command)
                assert (subprocess.run(brew_libomp_command,
                                       timeout=10,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE).returncode == 0)
            except subprocess.TimeoutExpired:
                print('Could not check required packages. Continuing...')
            except AssertionError:
                message = '''It seems that you have got Homebrew installed, which is great!
However, it seems you do not have the libomp package installed.
This is needed if you want to use OpenMP with the Clang C++ compiler.

Could you please try to install libomp with this command:

    brew install libomp

'''
                if platform.machine() != 'arm64':
                    message += '''
Or alternatively you can try to install GCC and use it instead of Clang:

    brew install gcc

'''
                message += '''Once you have done that, please try to run the same command again,
I should be able to find the right packages and compilers then!'''
                sys.exit(message)

            self = self.add_flag('-Xpreprocessor', '-fopenmp')
            self = self.add_flag('-I', f'{brew_dir}/include')
            if sys.argv[1] != 'assembly':
                self = self.add_flag('-lomp')
                self = self.add_flag('-L', f'{brew_dir}/lib')

        else:
            self = self.add_flag('-fopenmp')
        return self
コード例 #12
0
    def run(self, config, args: List[str],
            timeout: Optional[float]) -> RunnerOutput:
        env = os.environ.copy()

        ppc_output_read, ppc_output_write = os.pipe()
        env['PPC_OUTPUT'] = str(ppc_output_write)

        env['PPC_PERF'] = 'default'

        # Run with nvprof
        nvprof_output_file = tempfile.NamedTemporaryFile('r')
        args = [
            'nvprof',
            '--csv',
            '--log-file',
            nvprof_output_file.name,
            '--normalized-time-unit',
            's',
            '--print-gpu-trace',
            '--',
        ] + args

        log_command(args)
        process = subprocess.Popen(args,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE,
                                   stdin=subprocess.DEVNULL,
                                   env=env,
                                   encoding='utf-8',
                                   errors='utf-8',
                                   pass_fds=(ppc_output_write, ))
        os.close(ppc_output_write)

        try:
            stdout, stderr = process.communicate(None, timeout=timeout)
            run_successful = process.returncode == 0
            timed_out = False
        except subprocess.TimeoutExpired:
            run_successful = False
            timed_out = True
            try:
                # Ask nicely to terminate before killing
                process.terminate()
                stdout, stderr = process.communicate(None, timeout=1)
            except subprocess.TimeoutExpired:
                process.kill()
                stdout, stderr = process.communicate(None)

        # Read nvprof output
        nvprofoutput_raw = nvprof_output_file.read()
        nvprof_statistics = {}
        try:
            # First line should look something like
            # ==[PID]== NVPROF is profiling process [PID], command: [some command]
            # Let's parse the PID part and use ==PID== as a comment marker in the future
            first_line = nvprofoutput_raw.split('\n', 1)[0]
            m = re.match(r'^==(\d+)== (.*)', first_line)
            pid = m.group(1)
            section = m.group(2)
            r = re.compile(fr'^=={re.escape(pid)}== (.*?)$', re.MULTILINE)
            pos = m.end()
            while True:
                m = r.search(nvprofoutput_raw, pos)
                if m is None:
                    end = -1
                else:
                    end = m.start()

                content = nvprofoutput_raw[pos:end].strip()

                if section == 'Profiling result:':
                    gpu_trace = list(
                        csv.DictReader(io.StringIO(content),
                                       dialect=csv.unix_dialect))
                    # Skip units
                    gpu_trace = gpu_trace[1:]
                    nvprof_statistics['gpu_trace'] = gpu_trace

                if m is None:
                    break
                section = m.group(1)
                pos = m.end()
        except:
            # Parsing nvprof output failed
            pass

        if run_successful:
            output = os.fdopen(ppc_output_read, 'r').read()
            results = config.parse_output(output)
        else:
            os.close(ppc_output_read)
            results = []

        return NvprofRunnerOutput(nvprofoutput_raw, nvprof_statistics,
                                  run_successful, timed_out, stdout, stderr,
                                  timeout, *results)