reallocã使ã£ã¦ã¡ã¢ãªã¢ãã±ã¼ã·ã§ã³ã®ãµã¤ãºãå°ããã¤ä¼¸ã°ãã¦ããéã«ãåå´æéè¨ç®éã¯O(N)ã«ãªãã ããããããã¨ãO(N^2)ã ããããçµè«ã¨ãã¦ã¯ãæ®éã«ããã¨O(N^2)ã«ãªãããã ããã»ãªãªã¼éãã«ã¢ããªã±ã¼ã·ã§ã³å´ã§å·¥å¤«ããã¨O(N)ã«ã§ãããæ§è½ãã¹ãããã¦ãã¡ãã¨ç¢ºèªãã¦ãããã
é·ããäºåã«ããããªãæååãé åãæ±ãã«ã¯ãåçã«é åã確ä¿ããå¿ è¦ããããæ¨æºCè¨èªã«ã¯reallocã¨ããé¢æ°ããããããã¯æ¢åã®ç¢ºä¿é åãæ¡å¼µãããã¨ãå¯è½ã§ãããããã使ãã¨ãæ¢ã«ç¢ºä¿ãã¦ããé åã®ç´å¾ã«ã¾ã 確ä¿ããã¦ããªãé åããã£ã¦ãããåããã¦ç¢ºä¿ã§ããå ´åãé åã®å確ä¿ãããã«ãå©ç¨å¯è½ãªãµã¤ãºã ããå¢ããã¦ãããããããä¸å¯è½ãªå ´åãå¥ã®é åã確ä¿ãã¦ããæ¢åã®é åã®ãã¼ã¿ãã³ãã¼ãã¦ãå¤ãé åã¯åé¤ãã¦ããããC++ã®new/deleteã«ã¯ãã®æ©è½ã¯ãªãã
åãé åã«å¯¾ããreallocãé£ç¶ã§å¼ã¶å ´åãé å移åãªãã®ãµã¤ãºæ¡å¼µãå¯è½ã§ããã以ä¸ã®ä¾ã§ã¯1ã2ã¤åºåãããã¯ãã ãä»æ§ã¨ãã¦ã®ä¿è¨¼ã¯ãªããã©ã
void* p1 = realloc(nullptr, 100); void* p2 = realloc(p1, 200); std::cout << (p1 == p2) << std::endl; void* p3 = realloc(p2, 300); std::cout << (p2 == p3) << std::endl;
è¤æ°ã®é åã交äºã«æ¡å¼µãããã¨ããã¨ãããã¯ãããªãã以ä¸ã®ä¾ã§ã¯0ã2ã¤åºåãããã¯ãã ãä»æ§ã¨ãã¦ã®ä¿è¨¼ã¯ãªããã©ã
void* p1 = realloc(nullptr, 100); void* q1 = realloc(nullptr, 100); void* p2 = realloc(p1, 200); std::cout << (p1 == p2) << std::endl; void* q2 = realloc(q1, 200); std::cout << (q1 == q2) << std::endl;
æ¢ã«è¿°ã¹ãããreallocã«ããé åã®ç§»åã¯ãæ¢åé åã®å 容ã®è¤è£½ãä¼´ãããããã£ã¦ã1ãã¤ãã®é åã1ãã¤ããã¤ä¼¸ã°ãã¦Nãã¤ãã«ããä½æ¥ã2ã¤ã®é åã§äº¤äºã«è¡ã£ãã¨ãããããã®æéè¨ç®éã¯O(N^2)ã«ãªã£ã¦ãã¾ããreallocã®å®è£ ã¯é åã漸次çã«æ¡å¼µãããã¨ãããã¨ã¯åæã¨ãã¦ããªãã®ã§ãæ¬å½ã«äºæ¬¡é¢æ°ã®å¢ãã§é ããªãããªã®ã§æ®éã¯reallocãªã©ä½¿ããã«ãstd::stringã®appendã¡ã½ããã¨ããstd::striingstreamã®æ¿å ¥ãªãã¬ã¼ã¿ã¨ããvectorã®push_backã¡ã½ããã¨ãã使ãããããã¯å é¨ã®è¨æ¶é åãååã²ã¼ã ï¼å®éã¯factor=1.5ã¨ãï¼ã§å¢ããã®ã§ãåå´æéè¨ç®éã¯O(N)ã«ãªããããªãã¡ãææªã®ã±ã¼ã¹ã§ã¯æå¾ã®Nãã¤ãç®ã確ä¿ããéã«N-1ãã¤ãã®ã³ãã¼ãçºçãããããã®å ´åã¯ä»¥åã«(N-1)/2ãã¤ãã®ã³ãã¼ã¨(N-1)/4ãã¤ãã®ã³ãã¼ã¨(N-1)/8ãã¤ãã®ã³ãã¼ãªã©ãªã©ãçºçãã¦ããã¯ãã ããããããå ¨é¨è¶³ãã¦ãNã«éããªãã®ã§ãç·å½¢ãªã¼ãã¼ã¨ã¿ãªããããã ã
ã¨ããã§ãstd::stringã®appendã¨ãã便å©ãªã®ã«ãªãreallocã使ãã®ããããã¯ãstd::stringã¯ç©ºéå©ç¨ã«ç¡é§ãããããã ãmallocãreallocã®å®è£ ã®å é¨ã§ã¯ãå²ãå½ã¦ãé åã®ã¢ãã¬ã¹ã«ç´ã¥ãã¦å²ãå½ã¦ããµã¤ãºã管çãã¦ãããä¸æ¹ã§ãstd::stringãèªåãä½ãã¤ã確ä¿ããããå±æ§ã¨ãã¦æã£ã¦ãããããã§ãã¦ãstd::stringãå é¨ã§å¼ã¶newã¯çµå±mallocãå¼ã¶ã®ã§ãåãæ å ±ãäºç®æã§æã¤ãã¨ã«ãªããã¤ãã§ã«è¨ãã¨ãstd::stringã§ãstd::stringstreamã§ãstd::vectorã§ãã確ä¿ãµã¤ãºã®å±æ§ã¨å©ç¨ãµã¤ãºã®å±æ§ã¯å¥åã«æã¤å¿ è¦ããããä»è°è«ãã¦ããã®ã¯åè ã«ã¤ãã¦ã ã
ã¢ããªã±ã¼ã·ã§ã³å´ã§ç¢ºä¿ãµã¤ãºã®æ å ±ãæããªãã¦ããæ¯åreallocãå¼ããããã°ãããreallocãå¼ã¶éã«ãååã²ã¼ã ã§ãµã¤ãºã決ããã°ãstd::stringã®appendã使ããããå¹ççã«ãé·ããå¢ããæååãæ±ããã¨ãã§ãããå ·ä½çã«è¨ãã¨ã確ä¿ããããµã¤ãºãåãåã£ããããã以ä¸ã§æå°ã®2ã®åªããµã¤ãºã«ããã°ãããã¤ã¾ãã以ä¸ã®ãããªã³ã¼ãã«ãªãã8ãæå°å¤ã«ããã®ã¯çµé¨åã«ããæé©åã ã
void* PowerAlignedRealloc(bool alignment, void* ptr, size_t size) { size_t aligned_size = 8; while (aligned_size < size) { aligned_size *= 2; } return std::realloc(ptr, aligned_size); }
é åã®å確ä¿ãããªãå ´åã®reallocã¯ã確ä¿ãµã¤ãºã®å¤æ°ã調ã¹ãã ãã®ç°¡åãªãä»äºããããªãããã®éã«ã¯ã¹ã¬ããå®å ¨æ§ã®ããã«ä½ããã®æä»å¶å¾¡ãè¡ãããã¯ãã§ããããªãã®ã³ã¹ãããããå¯è½æ§ã¯ããããæéå¹çããã空éå¹çã®æ¹ã大äºã ã¨ããå ´é¢ãããã
æ§è½ãã¹ãããããã100ãã¤ããã¤ãµã¤ãºãå¢ãããªããã¡ã¢ãªé åã確ä¿ããå¦çã100åã®å¥åã®ã¬ã³ã¼ãã§è¡ããåã¬ã³ã¼ãã§1000åãã¤æ¡å¼µæä½ãè¡ãã1åç®ãã100åç®ã101åç®ãã200åç®ã...ã901åç®ãã1000åç®ã«ããã£ãçµéæéããããã測å®ãããçã®reallocã¨ãåªã¢ã©ã¤ã³ã¡ã³ãä»ãã®reallocã¨ãstd::stringã®appendã¡ã½ãããæ¯è¼ããã以ä¸ã®ããã°ã©ã ã ã
#include <chrono> #include <string> #include <cstdlib> #include <cassert> #include <iomanip> #include <iostream> constexpr int num_iterations = 1000; constexpr int num_records = 1000; constexpr int size_unit = 100; constexpr int check_unit = 100; double GetWallTime() { const auto epoch = std::chrono::time_point<std::chrono::system_clock>(); const auto current = std::chrono::system_clock::now(); const auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(current - epoch); return elapsed.count() / 1000000.0; } void* Realloc(bool alignment, void* old_ptr, size_t size) { if (alignment) { size_t aligned_size = 8; while (aligned_size < size) { aligned_size *= 2; } size = aligned_size; } void* new_ptr = std::realloc(old_ptr, size); assert(new_ptr != nullptr); return new_ptr; } void TestRealloc(bool alignment) { std::cout << "-- Realloc alignment=" << alignment << " --" << std::endl; void* records[num_records]; for (int record_index = 0; record_index < num_records; record_index++) { records[record_index] = nullptr; } int size = size_unit; double start_time = GetWallTime(); for (int iteration_count = 1; iteration_count <= num_iterations; iteration_count++) { for (int record_index = 0; record_index < num_records; record_index++) { records[record_index] = Realloc(alignment, records[record_index], size); } if (iteration_count % check_unit == 0) { const double end_time = GetWallTime(); std::cout << "iteration=" << iteration_count << " size=" << size << " time=" << end_time - start_time << std::endl; start_time = GetWallTime(); } size += size_unit; } } void TestString() { std::cout << "-- std::string --" << std::endl; std::string records[num_records]; std::string unit(size_unit, 0); double start_time = GetWallTime(); for (int iteration_count = 1; iteration_count <= num_iterations; iteration_count++) { for (int record_index = 0; record_index < num_records; record_index++) { records[record_index].append(unit); } if (iteration_count % check_unit == 0) { const double end_time = GetWallTime(); std::cout << "iteration=" << iteration_count << " size=" << records[0].size() << " time=" << end_time - start_time << std::endl; start_time = GetWallTime(); } } } int main(int argc, char** argv) { std::cout << std::fixed; std::cout << std::setprecision(4); TestRealloc(false); TestRealloc(true); TestString(); return 0; }
çµæã¯ãããªæããåä½ã¯ç§ã
default realloc | aligned realloc | std::string | |
1-100 | 0.1311 | 0.0092 | 0.0116 |
101-200 | 0.4607 | 0.0142 | 0.0177 |
201-300 | 0.7554 | 0.0044 | 0.0286 |
301-400 | 1.0436 | 0.0272 | 0.0107 |
401-500 | 1.3101 | 0.0040 | 0.0113 |
501-600 | 1.5381 | 0.0040 | 0.0488 |
601-700 | 1.7880 | 0.0504 | 0.0152 |
701-800 | 1.9643 | 0.0046 | 0.0136 |
801-900 | 2.1867 | 0.0045 | 0.0139 |
901-1000 | 2.3064 | 0.0045 | 0.0132 |
çã®reallocãé ãã®ã¯äºæ³éãã ãä¸æ¹ã§ãåªã¢ã©ã¤ã³ã¡ã³ãããå ´åã¯ãã¡ããã¡ãæ©ãã8, 16, 32, 64, 128, 256, 512ãè·¨ãã¨ããã§ãããã1åãã¤ã®è¤è£½ãçºçããã®ã§ãããã ãã»ãã®ã¡ãã£ã¨ã³ã¹ããããããããã以å¤ã¯å¹é£ã®æéããããããªããåè¨æ¸¬ãã©ã±ããã§1ä¸åã®reallocãå¼ãã§ããã®ã§ãä½ãããªãreallocã«ãããæéã¯4ãã¤ã¯ãç§ä»¥ä¸ã¨è¨ãããæ¯åå¼ãã§ããããªã«çããªããã»ãã®ã¡ãã£ã¨å·¥å¤«ããã°2以å¤ã®factorã§ãå®è£ ã§ããã®ã§ãæéã¨ç©ºéã®ãã¬ã¼ããªãã¯ä»»æã«èª¿æ´ã§ãããstd::stringã®appendã¡ã½ããã®æ§è½ãåããããªå¾åã§ããã¡ãæ©ããreallocã®æ¹ãå°ãæ©ãã®ã¯ãreallocã®ãã¹ãã§ã¯é£çµããæ«ç«¯é¨åã®æååã®åæåããµãã£ã¦ããã¨ããçç±ãå°ãã¯ããããæ¬è³ªçã«reallocã®æ¹ãnew/deleteã®çµã¿åããããæ©ãã¨ããçç±ã大ãããã¨ã¯ããstd::stringãååæ©ãã
ã¾ã¨ããé åã®ãµã¤ãºã漸å¢ãããå®è£ ãèªåã§æ¸ãå ´åãreallocã®å段ã«ãµã¤ãºã調æ´ããå¦çãå ¥ããã ãã§ã確ä¿ãããµã¤ãºã®å±æ§ãã¢ããªã±ã¼ã·ã§ã³å´ã§æããã¨ããåå´æéè¨ç®éãO(N)ã«ã§ãããstd::stringã«æ¯ã¹ã¦ããµã¤ãºã®ããã®å¤æ°1ã¤åã8ãã¤ãã®ã¡ã¢ãªç¯ç´ã«ãªããå¤ãã®å ´åã¯ãããªãã¨ã¯ããã«æ®éã«std::stringãstd::vectorã使ãã°è¯ãã®ã ããå°ããé åã大éã«æã¤å ´åã«ã¯ãã®ç¯ç´ã¯å°å³ã«å¹ãã¦ããã転置索å¼ã®ãã¹ãã£ã³ã°ãªã¹ãã表ãã®ã«ãã®æ¹æ³ã¯æé©ã ãããã«ã¤ãã¦ã¯ã¾ãæ¹ãã¦èå¯ããã