49
49
#include < inttypes.h>
50
50
#endif
51
51
52
+ #include " opencv2/core/ocl_genbase.hpp"
53
+
52
54
#define CV_OPENCL_ALWAYS_SHOW_BUILD_LOG 0
53
55
#define CV_OPENCL_SHOW_RUN_ERRORS 0
54
56
#define CV_OPENCL_SHOW_SVM_ERROR_LOG 1
@@ -1259,6 +1261,18 @@ static unsigned int getSVMCapabilitiesMask()
1259
1261
} // namespace
1260
1262
#endif
1261
1263
1264
+ static size_t getProgramCountLimit ()
1265
+ {
1266
+ static bool initialized = false ;
1267
+ static size_t count = 0 ;
1268
+ if (!initialized)
1269
+ {
1270
+ count = getConfigurationParameterForSize (" OPENCV_OPENCL_PROGRAM_CACHE" , 64 );
1271
+ initialized = true ;
1272
+ }
1273
+ return count;
1274
+ }
1275
+
1262
1276
struct Context ::Impl
1263
1277
{
1264
1278
static Context::Impl* get (Context& context) { return context.p ; }
@@ -1378,35 +1392,57 @@ struct Context::Impl
1378
1392
Program getProg (const ProgramSource& src,
1379
1393
const String& buildflags, String& errmsg)
1380
1394
{
1381
- String prefix = Program::getPrefix (buildflags);
1382
- HashKey k (src.hash (), crc64 ((const uchar*)prefix.c_str (), prefix.size ()));
1383
- phash_t ::iterator it = phash.find (k);
1384
- if ( it != phash.end () )
1385
- return it->second ;
1386
- // String filename = format("%08x%08x_%08x%08x.clb2",
1395
+ size_t limit = getProgramCountLimit ();
1396
+ String key = Program::getPrefix (buildflags);
1397
+ {
1398
+ cv::AutoLock lock (program_cache_mutex);
1399
+ phash_t ::iterator it = phash.find (key);
1400
+ if (it != phash.end ())
1401
+ {
1402
+ // TODO LRU cache
1403
+ CacheList::iterator i = std::find (cacheList.begin (), cacheList.end (), key);
1404
+ if (i != cacheList.end () && i != cacheList.begin ())
1405
+ {
1406
+ cacheList.erase (i);
1407
+ cacheList.push_front (key);
1408
+ }
1409
+ return it->second ;
1410
+ }
1411
+ { // cleanup program cache
1412
+ size_t sz = phash.size ();
1413
+ if (limit > 0 && sz >= limit)
1414
+ {
1415
+ while (!cacheList.empty ())
1416
+ {
1417
+ size_t c = phash.erase (cacheList.back ());
1418
+ cacheList.pop_back ();
1419
+ if (c != 0 )
1420
+ break ;
1421
+ }
1422
+ }
1423
+ }
1424
+ }
1387
1425
Program prog (src, buildflags, errmsg);
1388
1426
if (prog.ptr ())
1389
- phash.insert (std::pair<HashKey,Program>(k, prog));
1427
+ {
1428
+ cv::AutoLock lock (program_cache_mutex);
1429
+ phash.insert (std::pair<std::string, Program>(key, prog));
1430
+ cacheList.push_front (key);
1431
+ }
1390
1432
return prog;
1391
1433
}
1392
1434
1435
+
1393
1436
IMPLEMENT_REFCOUNTABLE ();
1394
1437
1395
1438
cl_context handle;
1396
1439
std::vector<Device> devices;
1397
1440
1398
- typedef ProgramSource::hash_t hash_t ;
1399
-
1400
- struct HashKey
1401
- {
1402
- HashKey (hash_t _a, hash_t _b) : a(_a), b(_b) {}
1403
- bool operator < (const HashKey& k) const { return a < k.a || (a == k.a && b < k.b ); }
1404
- bool operator == (const HashKey& k) const { return a == k.a && b == k.b ; }
1405
- bool operator != (const HashKey& k) const { return a != k.a || b != k.b ; }
1406
- hash_t a, b;
1407
- };
1408
- typedef std::map<HashKey, Program> phash_t ;
1441
+ cv::Mutex program_cache_mutex;
1442
+ typedef std::map<std::string, Program> phash_t ;
1409
1443
phash_t phash;
1444
+ typedef std::list<cv::String> CacheList;
1445
+ CacheList cacheList;
1410
1446
1411
1447
#ifdef HAVE_OPENCL_SVM
1412
1448
bool svmInitialized;
@@ -2580,24 +2616,46 @@ String Program::getPrefix(const String& buildflags)
2580
2616
2581
2617
struct ProgramSource ::Impl
2582
2618
{
2583
- Impl (const char * _src )
2619
+ Impl (const String& src )
2584
2620
{
2585
- init (String (_src ));
2621
+ init (cv:: String (), cv::String (), src, cv::String ( ));
2586
2622
}
2587
- Impl (const String& _src )
2623
+ Impl (const String& module , const String& name, const String& codeStr, const String& codeHash )
2588
2624
{
2589
- init (_src );
2625
+ init (module , name, codeStr, codeHash );
2590
2626
}
2591
- void init (const String& _src )
2627
+ void init (const String& module , const String& name, const String& codeStr, const String& codeHash )
2592
2628
{
2593
2629
refcount = 1 ;
2594
- src = _src;
2595
- h = crc64 ((uchar*)src.c_str (), src.size ());
2630
+ module_ = module ;
2631
+ name_ = name;
2632
+ codeStr_ = codeStr;
2633
+ codeHash_ = codeHash;
2634
+
2635
+ isHashUpdated = false ;
2636
+ if (codeHash_.empty ())
2637
+ {
2638
+ updateHash ();
2639
+ codeHash_ = cv::format (" %08llx" , hash_);
2640
+ }
2641
+ }
2642
+
2643
+ void updateHash ()
2644
+ {
2645
+ hash_ = crc64 ((uchar*)codeStr_.c_str (), codeStr_.size ());
2646
+ isHashUpdated = true ;
2596
2647
}
2597
2648
2598
2649
IMPLEMENT_REFCOUNTABLE ();
2599
- String src;
2600
- ProgramSource::hash_t h;
2650
+
2651
+ String module_;
2652
+ String name_;
2653
+ String codeStr_;
2654
+ String codeHash_;
2655
+ // TODO std::vector<ProgramSource> includes_;
2656
+
2657
+ bool isHashUpdated;
2658
+ ProgramSource::hash_t hash_;
2601
2659
};
2602
2660
2603
2661
@@ -2606,6 +2664,11 @@ ProgramSource::ProgramSource()
2606
2664
p = 0 ;
2607
2665
}
2608
2666
2667
+ ProgramSource::ProgramSource (const String& module , const String& name, const String& codeStr, const String& codeHash)
2668
+ {
2669
+ p = new Impl (module , name, codeStr, codeHash);
2670
+ }
2671
+
2609
2672
ProgramSource::ProgramSource (const char * prog)
2610
2673
{
2611
2674
p = new Impl (prog);
@@ -2642,15 +2705,34 @@ ProgramSource& ProgramSource::operator = (const ProgramSource& prog)
2642
2705
2643
2706
const String& ProgramSource::source () const
2644
2707
{
2645
- static String dummy ;
2646
- return p ? p-> src : dummy ;
2708
+ CV_Assert (p) ;
2709
+ return p-> codeStr_ ;
2647
2710
}
2648
2711
2649
2712
ProgramSource::hash_t ProgramSource::hash () const
2650
2713
{
2651
- return p ? p->h : 0 ;
2714
+ CV_Assert (p);
2715
+ if (!p->isHashUpdated )
2716
+ p->updateHash ();
2717
+ return p->hash_ ;
2652
2718
}
2653
2719
2720
+
2721
+ internal::ProgramEntry::operator ProgramSource&() const
2722
+ {
2723
+ if (this ->pProgramSource == NULL )
2724
+ {
2725
+ cv::AutoLock lock (cv::getInitializationMutex ());
2726
+ if (this ->pProgramSource == NULL )
2727
+ {
2728
+ ProgramSource* ps = new ProgramSource (this ->module , this ->name , this ->programCode , this ->programHash );
2729
+ const_cast <ProgramEntry*>(this )->pProgramSource = ps;
2730
+ }
2731
+ }
2732
+ return *this ->pProgramSource ;
2733
+ }
2734
+
2735
+
2654
2736
// ////////////////////////////////////////// OpenCLAllocator //////////////////////////////////////////////////
2655
2737
2656
2738
template <typename T>
0 commit comments