diff options
| -rw-r--r-- | CHANGES | 12 | ||||
| -rw-r--r-- | libcuda/cuda_runtime_api.cc | 7 | ||||
| -rw-r--r-- | src/abstract_hardware_model.h | 8 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.cc | 16 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-cache.h | 58 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.cc | 98 | ||||
| -rw-r--r-- | src/gpgpu-sim/gpu-sim.h | 19 | ||||
| -rw-r--r-- | src/gpgpu-sim/shader.h | 16 | ||||
| -rw-r--r-- | src/stream_manager.cc | 3 |
9 files changed, 194 insertions, 43 deletions
@@ -10,7 +10,17 @@ Version 3.2.1+edits (development branch) versus 3.2.1 and CL_DEVICE_TYPE_GPU. Before only CL_DEVICE_TYPE_GPU is accepted. - Fix for Bug 53 - Returning the CL_DEVICE_TYPE property in proper size from clGetDeviceInfo(...). - - Fix for Bug 54 - Added code to automatically determine workgroup size. + - Fix for Bug 54 - Added code to automatically determine workgroup size. + - Adding support for cudaFuncSetCacheConfig API, that allows changing the + L1 Cache and Shared Memory configurations across kernels. The support + enable the user to specify two more configurations (Preferred L1) or + (Preferred Shared Memory) besides the default config. If the + cudaFuncSetCacheConfig API is used to set the cache configuration + of a specific kernel to either of these configuration (cudaFuncCachePreferShared, + cudaFuncCachePreferL1), the simulator will change the cache configuration + at kernel launch accordingly, if there is no alternative configurations + provided to the simulator it will use the default configurations with a + warning message display Version 3.2.1 versus 3.2.0 - Added kernel name and launch uids to performance statistics log. - Added l2_cache_config class to extend baseline cache_config. Allows for diff --git a/libcuda/cuda_runtime_api.cc b/libcuda/cuda_runtime_api.cc index dad7669..7cb4ec4 100644 --- a/libcuda/cuda_runtime_api.cc +++ b/libcuda/cuda_runtime_api.cc @@ -787,6 +787,13 @@ __host__ cudaError_t CUDARTAPI cudaGetDevice(int *device) return g_last_cudaError = cudaSuccess; } +__host__ cudaError_t CUDARTAPI cudaFuncSetCacheConfig(const char *func, enum cudaFuncCache cacheConfig ) +{ + CUctx_st *context = GPGPUSim_Context(); + context->get_device()->get_gpgpu()->set_cache_config(context->get_kernel(func)->get_name(), (FuncCache)cacheConfig); + return g_last_cudaError = cudaSuccess; +} + /******************************************************************************* * * * * diff --git a/src/abstract_hardware_model.h b/src/abstract_hardware_model.h index de6eef8..5d74651 100644 --- a/src/abstract_hardware_model.h +++ b/src/abstract_hardware_model.h @@ -226,6 +226,9 @@ struct core_config { m_valid = false; num_shmem_bank=16; shmem_limited_broadcast = false; + gpgpu_shmem_sizeDefault=(unsigned)-1; + gpgpu_shmem_sizePrefL1=(unsigned)-1; + gpgpu_shmem_sizePrefShared=(unsigned)-1; } virtual void init() = 0; @@ -244,7 +247,10 @@ struct core_config { return ((addr/WORD_SIZE) % num_shmem_bank); } unsigned mem_warp_parts; - unsigned gpgpu_shmem_size; + mutable unsigned gpgpu_shmem_size; + unsigned gpgpu_shmem_sizeDefault; + unsigned gpgpu_shmem_sizePrefL1; + unsigned gpgpu_shmem_sizePrefShared; // texture and constant cache line sizes (used to determine number of memory accesses) unsigned gpgpu_cache_texl1_linesize; diff --git a/src/gpgpu-sim/gpu-cache.cc b/src/gpgpu-sim/gpu-cache.cc index d5856aa..3d8d911 100644 --- a/src/gpgpu-sim/gpu-cache.cc +++ b/src/gpgpu-sim/gpu-cache.cc @@ -29,6 +29,9 @@ #include "stat-tool.h" #include <assert.h> +#define MAX_DEFAULT_CACHE_SIZE_MULTIBLIER 4 +// used to allocate memory that is large enough to adapt the changes in cache size across kernels + const char * cache_request_status_str(enum cache_request_status status) { static const char * static_cache_request_status_str[] = { @@ -45,7 +48,7 @@ const char * cache_request_status_str(enum cache_request_status status) } void l2_cache_config::init(linear_to_raw_address_translation *address_mapping){ - cache_config::init(); + cache_config::init(m_config_string); m_address_mapping = address_mapping; } @@ -64,7 +67,7 @@ tag_array::~tag_array() delete[] m_lines; } -tag_array::tag_array( const cache_config &config, +tag_array::tag_array( cache_config &config, int core_id, int type_id, cache_block_t* new_lines) @@ -74,13 +77,18 @@ tag_array::tag_array( const cache_config &config, init( core_id, type_id ); } -tag_array::tag_array( const cache_config &config, +void tag_array::update_cache_parameters(cache_config &config) +{ + m_config=config; +} + +tag_array::tag_array( cache_config &config, int core_id, int type_id ) : m_config( config ) { //assert( m_config.m_write_policy == READ_ONLY ); Old assert - m_lines = new cache_block_t[ config.get_num_lines()]; + m_lines = new cache_block_t[MAX_DEFAULT_CACHE_SIZE_MULTIBLIER*config.get_num_lines()]; init( core_id, type_id ); } diff --git a/src/gpgpu-sim/gpu-cache.h b/src/gpgpu-sim/gpu-cache.h index 4910ca2..dd56d9f 100644 --- a/src/gpgpu-sim/gpu-cache.h +++ b/src/gpgpu-sim/gpu-cache.h @@ -131,19 +131,21 @@ public: m_valid = false; m_disabled = false; m_config_string = NULL; // set by option parser + m_config_stringPrefL1 = NULL; + m_config_stringPrefShared = NULL; } - void init() + void init(char * config) { - assert( m_config_string ); + assert( config ); char rp, wp, ap, mshr_type, wap; - int ntok = sscanf(m_config_string,"%u:%u:%u,%c:%c:%c:%c,%c:%u:%u,%u:%u", + int ntok = sscanf(config,"%u:%u:%u,%c:%c:%c:%c,%c:%u:%u,%u:%u", &m_nset, &m_line_sz, &m_assoc, &rp, &wp, &ap, &wap, &mshr_type, &m_mshr_entries,&m_mshr_max_merge, &m_miss_queue_size,&m_result_fifo_entries); - if ( ntok < 10 ) { - if ( !strcmp(m_config_string,"none") ) { + if ( ntok < 11 ) { + if ( !strcmp(config,"none") ) { m_disabled = true; return; } @@ -235,6 +237,8 @@ public: } char *m_config_string; + char *m_config_stringPrefL1; + char *m_config_stringPrefShared; protected: void exit_parse_error() @@ -295,7 +299,7 @@ private: class tag_array { public: // Use this constructor - tag_array( const cache_config &config, int core_id, int type_id ); + tag_array(cache_config &config, int core_id, int type_id ); ~tag_array(); enum cache_request_status probe( new_addr_type addr, unsigned &idx ) const; @@ -314,12 +318,12 @@ public: void print( FILE *stream, unsigned &total_access, unsigned &total_misses ) const; float windowed_miss_rate( ) const; void get_stats(unsigned &total_access, unsigned &total_misses) const; - + void update_cache_parameters(cache_config &config); protected: // This constructor is intended for use only from derived classes that wish to // avoid unnecessary memory allocation that takes place in the // other tag_array constructor - tag_array( const cache_config &config, + tag_array( cache_config &config, int core_id, int type_id, cache_block_t* new_lines ); @@ -327,7 +331,7 @@ protected: protected: - const cache_config &m_config; + cache_config &m_config; cache_block_t *m_lines; /* nbanks x nset x assoc lines in total */ @@ -372,6 +376,12 @@ public: mem_fetch *next_access(); void display( FILE *fp ) const; + void check_mshr_parameters( unsigned num_entries, unsigned max_merged ) + { + assert(m_num_entries==num_entries && "Change of MSHR parameters between kernels is not allowed"); + assert(m_max_merged==max_merged && "Change of MSHR parameters between kernels is not allowed"); + } + private: // finite sized, fully associative table, with a finite maximum number of merged requests @@ -408,7 +418,7 @@ bool was_read_sent( const std::list<cache_event> &events ); /// Each subclass implements its own 'access' function class baseline_cache : public cache_t { public: - baseline_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, + baseline_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) : m_config(config), m_tag_array(new tag_array(config,core_id,type_id)), m_mshrs(config.m_mshr_entries,config.m_mshr_max_merge) { @@ -435,6 +445,13 @@ public: delete m_tag_array; } + void update_cache_parameters(cache_config &config) + { + m_config=config; + m_tag_array->update_cache_parameters(config); + m_mshrs.check_mshr_parameters(config.m_mshr_entries,config.m_mshr_max_merge); + } + virtual enum cache_request_status access( new_addr_type addr, mem_fetch *mf, unsigned time, std::list<cache_event> &events ) = 0; /// Sends next request to lower level of memory void cycle(); @@ -465,7 +482,7 @@ public: protected: // Constructor that can be used by derived classes with custom tag arrays baseline_cache( const char *name, - const cache_config &config, + cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, @@ -480,7 +497,7 @@ protected: protected: std::string m_name; - const cache_config &m_config; + cache_config &m_config; tag_array* m_tag_array; mshr_table m_mshrs; std::list<mem_fetch*> m_miss_queue; @@ -527,7 +544,7 @@ protected: /// Read only cache class read_only_cache : public baseline_cache { public: - read_only_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) + read_only_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status ) : baseline_cache(name,config,core_id,type_id,memport,status){} /// Access cache for read_only_cache: returns RESERVATION_FAIL if request could not be accepted (for any reason) @@ -536,14 +553,14 @@ public: virtual ~read_only_cache(){} protected: - read_only_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status, tag_array* new_tag_array ) + read_only_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status status, tag_array* new_tag_array ) : baseline_cache(name,config,core_id,type_id,memport,status, new_tag_array){} }; /// Data cache - Implements common functions for L1 and L2 data cache class data_cache : public baseline_cache { public: - data_cache( const char *name, const cache_config &config, + data_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : baseline_cache(name,config,core_id,type_id,memport,status) @@ -581,9 +598,10 @@ public: } } + protected: data_cache( const char *name, - const cache_config &config, + cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, @@ -636,7 +654,7 @@ protected: /// (the policy used in fermi according to the CUDA manual) class l1_cache : public data_cache { public: - l1_cache(const char *name, const cache_config &config, + l1_cache(const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : data_cache(name,config,core_id,type_id,memport,mfcreator,status){} @@ -647,7 +665,7 @@ public: protected: l1_cache( const char *name, - const cache_config &config, + cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, @@ -661,7 +679,7 @@ protected: /// Models second level shared cache with global write-back and write-allocate policies class l2_cache : public data_cache { public: - l2_cache(const char *name, const cache_config &config, + l2_cache(const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, mem_fetch_allocator *mfcreator, enum mem_fetch_status status ) : data_cache(name,config,core_id,type_id,memport,mfcreator,status){} @@ -681,7 +699,7 @@ public: // http://www-graphics.stanford.edu/papers/texture_prefetch/ class tex_cache : public cache_t { public: - tex_cache( const char *name, const cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, + tex_cache( const char *name, cache_config &config, int core_id, int type_id, mem_fetch_interface *memport, enum mem_fetch_status request_status, enum mem_fetch_status rob_status ) : m_config(config), diff --git a/src/gpgpu-sim/gpu-sim.cc b/src/gpgpu-sim/gpu-sim.cc index 4cd9ea0..284b5ea 100644 --- a/src/gpgpu-sim/gpu-sim.cc +++ b/src/gpgpu-sim/gpu-sim.cc @@ -212,10 +212,19 @@ void shader_core_config::reg_options(class OptionParser * opp) "shader L1 instruction cache config " " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq>} ", "4:256:4,L:R:f:N,A:2:32,4" ); - option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_L1D_config.m_config_string, + option_parser_register(opp, "-gpgpu_cache:dl1", OPT_CSTR, &m_L1D_config.m_config_string, "per-shader L1 data cache config " " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", "none" ); + option_parser_register(opp, "-gpgpu_cache:dl1PrefL1", OPT_CSTR, &m_L1D_config.m_config_stringPrefL1, + "per-shader L1 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", + "none" ); + option_parser_register(opp, "-gpgpu_cache:dl1PreShared", OPT_CSTR, &m_L1D_config.m_config_stringPrefShared, + "per-shader L1 data cache config " + " {<nsets>:<bsize>:<assoc>,<rep>:<wr>:<alloc>:<wr_alloc>,<mshr>:<N>:<merge>,<mq> | none}", + "none" ); + option_parser_register(opp, "-gpgpu_perfect_mem", OPT_BOOL, &gpgpu_perfect_mem, "enable perfect memory mode (no cache miss)", "0"); @@ -246,7 +255,13 @@ void shader_core_config::reg_options(class OptionParser * opp) option_parser_register(opp, "-gpgpu_n_ldst_response_buffer_size", OPT_UINT32, &ldst_unit_response_queue_size, "number of response packets in ld/st unit ejection buffer", "2"); - option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_size, + option_parser_register(opp, "-gpgpu_shmem_size", OPT_UINT32, &gpgpu_shmem_sizeDefault, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-gpgpu_shmem_size_PrefL1", OPT_UINT32, &gpgpu_shmem_sizePrefL1, + "Size of shared memory per shader core (default 16kB)", + "16384"); + option_parser_register(opp, "-gpgpu_shmem_size_PrefShared", OPT_UINT32, &gpgpu_shmem_sizePrefShared, "Size of shared memory per shader core (default 16kB)", "16384"); option_parser_register(opp, "-gpgpu_shmem_num_banks", OPT_UINT32, &num_shmem_bank, @@ -473,7 +488,6 @@ kernel_info_t *gpgpu_sim::select_kernel() unsigned idx = (n+m_last_issued_kernel+1)%m_config.max_concurrent_kernel; if( m_running_kernels[idx] && !m_running_kernels[idx]->no_more_ctas_to_run() ) { m_last_issued_kernel=idx; - // record this kernel for stat print if it is the first time this kernel is selected for execution unsigned launch_uid = m_running_kernels[idx]->get_uid(); if (std::find(m_executed_kernel_uids.begin(), m_executed_kernel_uids.end(), launch_uid) == m_executed_kernel_uids.end()) { @@ -754,13 +768,85 @@ std::string gpgpu_sim::executed_kernel_info_string() return statout.str(); } +void gpgpu_sim::set_cache_config(std::string kernel_name, FuncCache cacheConfig ) +{ + m_special_cache_config[kernel_name]=cacheConfig ; +} -void gpgpu_sim::clear_executed_kernel_info() +FuncCache gpgpu_sim::get_cache_config(std::string kernel_name) { - m_executed_kernel_names.clear(); - m_executed_kernel_uids.clear(); + for ( std::map<std::string, FuncCache>::iterator iter = m_special_cache_config.begin(); iter != m_special_cache_config.end(); iter++){ + std::string kernel= iter->first; + if (kernel_name.compare(kernel) == 0){ + return iter->second; + } + } + return (FuncCache)0; } +bool gpgpu_sim::has_special_cache_config(std::string kernel_name) +{ + for ( std::map<std::string, FuncCache>::iterator iter = m_special_cache_config.begin(); iter != m_special_cache_config.end(); iter++){ + std::string kernel= iter->first; + if (kernel_name.compare(kernel) == 0){ + return true; + } + } + return false; +} + + +void gpgpu_sim::set_cache_config(std::string kernel_name) +{ + if(has_special_cache_config(kernel_name)){ + change_cache_config(get_cache_config(kernel_name)); + }else{ + change_cache_config(FuncCachePreferNone); + } +} + + +void gpgpu_sim::change_cache_config(FuncCache cache_config) +{ + switch(cache_config){ + case FuncCachePreferNone: + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + break; + case FuncCachePreferL1: + if((m_shader_config->m_L1D_config.m_config_stringPrefL1 == NULL) || (m_shader_config->gpgpu_shmem_sizePrefL1 == (unsigned)-1)) + { + printf("WARNING: missing Preferred L1 configuration\n"); + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + + }else{ + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_stringPrefL1); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizePrefL1; + } + break; + case FuncCachePreferShared: + if((m_shader_config->m_L1D_config.m_config_stringPrefShared == NULL) || (m_shader_config->gpgpu_shmem_sizePrefShared == (unsigned)-1)) + { + printf("WARNING: missing Preferred L1 configuration\n"); + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_string); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizeDefault; + }else{ + m_shader_config->m_L1D_config.init(m_shader_config->m_L1D_config.m_config_stringPrefShared); + m_shader_config->gpgpu_shmem_size=m_shader_config->gpgpu_shmem_sizePrefShared; + } + break; + default: + break; + } +} + + +void gpgpu_sim::clear_executed_kernel_info() +{ + m_executed_kernel_names.clear(); + m_executed_kernel_uids.clear(); +} void gpgpu_sim::gpu_print_stat() { FILE *statfout = stdout; diff --git a/src/gpgpu-sim/gpu-sim.h b/src/gpgpu-sim/gpu-sim.h index 8572092..8616fd4 100644 --- a/src/gpgpu-sim/gpu-sim.h +++ b/src/gpgpu-sim/gpu-sim.h @@ -35,7 +35,6 @@ #include "shader.h" #include <iostream> #include <fstream> - #include <list> #include <stdio.h> @@ -72,6 +71,14 @@ enum dram_ctrl_t { DRAM_FRFCFS=1 }; +enum FuncCache +{ + FuncCachePreferNone = 0, + FuncCachePreferShared = 1, + FuncCachePreferL1 = 2 +}; + + struct power_config { power_config() @@ -210,7 +217,7 @@ struct memory_config { void reg_options(class OptionParser * opp); bool m_valid; - l2_cache_config m_L2_config; + mutable l2_cache_config m_L2_config; bool m_L2_texure_only; char *gpgpu_dram_timing_opt; @@ -461,6 +468,9 @@ private: unsigned long long gpu_tot_issued_cta; unsigned long long last_gpu_sim_insn; + + std::map<std::string, FuncCache> m_special_cache_config; + std::vector<std::string> m_executed_kernel_names; //< names of kernel for stat printout std::vector<unsigned> m_executed_kernel_uids; //< uids of kernel launches for stat printout std::string executed_kernel_info_string(); //< format the kernel information into a string for stat printout @@ -474,6 +484,11 @@ public: + FuncCache get_cache_config(std::string kernel_name); + void set_cache_config(std::string kernel_name, FuncCache cacheConfig ); + bool has_special_cache_config(std::string kernel_name); + void change_cache_config(FuncCache cache_config); + void set_cache_config(std::string kernel_name); }; diff --git a/src/gpgpu-sim/shader.h b/src/gpgpu-sim/shader.h index ba63634..4f5342f 100644 --- a/src/gpgpu-sim/shader.h +++ b/src/gpgpu-sim/shader.h @@ -1208,10 +1208,10 @@ struct shader_core_config : public core_config assert( !(n_thread_per_shader % warp_size) ); max_sfu_latency = 512; max_sp_latency = 32; - m_L1I_config.init(); - m_L1T_config.init(); - m_L1C_config.init(); - m_L1D_config.init(); + m_L1I_config.init(m_L1I_config.m_config_string); + m_L1T_config.init(m_L1T_config.m_config_string); + m_L1C_config.init(m_L1C_config.m_config_string); + m_L1D_config.init(m_L1D_config.m_config_string); gpgpu_cache_texl1_linesize = m_L1T_config.get_line_sz(); gpgpu_cache_constl1_linesize = m_L1C_config.get_line_sz(); m_valid = true; @@ -1239,10 +1239,10 @@ struct shader_core_config : public core_config char* pipeline_widths_string; int pipe_widths[N_PIPELINE_STAGES]; - cache_config m_L1I_config; - cache_config m_L1T_config; - cache_config m_L1C_config; - cache_config m_L1D_config; + mutable cache_config m_L1I_config; + mutable cache_config m_L1T_config; + mutable cache_config m_L1C_config; + mutable cache_config m_L1D_config; bool gpgpu_dwf_reg_bankconflict; diff --git a/src/stream_manager.cc b/src/stream_manager.cc index 6d5737f..3b8f57f 100644 --- a/src/stream_manager.cc +++ b/src/stream_manager.cc @@ -152,7 +152,8 @@ void stream_operation::do_operation( gpgpu_sim *gpu ) break; case stream_kernel_launch: if( gpu->can_start_kernel() ) { - printf("kernel \'%s\' transfer to GPU hardware scheduler\n", m_kernel->name().c_str() ); + gpu->set_cache_config(m_kernel->name()); + printf("kernel \'%s\' transfer to GPU hardware scheduler\n", m_kernel->name().c_str() ); if( m_sim_mode ) gpgpu_cuda_ptx_sim_main_func( *m_kernel ); else |
